import unittest
import time
from config.AppConfig import read_config
from app.Nema import NemaBase, NemaGGA, NemaVTG


gga_stub_data = 'GPGGA,210230,3855.4487,N,09446.0071,W,1,07,1.1,370.5,M,-29.5,M,,'
gga_stub_cksum = '7A'
gga_stub = '$' + gga_stub_data + '*' + gga_stub_cksum

vtg_stub_data = 'GPVTG,309.62,T, ,M,0.13,N,0.2,K,A'
vtg_stub_cksum = '23'
vtg_stub = '$' + vtg_stub_data + '*' + vtg_stub_cksum


# Chad's spec:
gga_stub2_data = 'GPGGA,210230,3855.449,N,09446.007,E,1,08,0.9,-10.0,M,46.9,M,,'
gga_stub2_cksum = '5C'
gga_stub2 = '$' + gga_stub2_data + '*' + gga_stub2_cksum

vtg_stub2_data = 'GPVTG,309.6,T,XXX.X,M,1.94,N,3.60,K'
vtg_stub2_cksum = '4B'
vtg_stub2 = '$' + vtg_stub2_data + '*' + vtg_stub2_cksum

cfg = read_config()


class NEMATestCase(unittest.TestCase):

    def test_decde2dms(self):
        nema = NemaBase()
        dd = 36.797
        degrees, minutes, seconds = nema.decimal_deg_to_deg_min_sec(dd)
        self.assertEqual(degrees, 36)
        self.assertEqual(minutes, 47)
        self.assertAlmostEqual(seconds, 49.2)


        dd = -121.847
        degrees, minutes, seconds = nema.decimal_deg_to_deg_min_sec(dd)
        self.assertEqual(degrees, 121)
        self.assertEqual(minutes, 50)
        self.assertAlmostEqual(seconds, 49.2)

    def test_decdeg2nema_decmin(self):
        nema = NemaBase()
        lat_dd = 36.797
        lon_dd = -121.847
        lat, lat_dir = nema.decimal_deg_to_nema_dec_min(lat_dd, 'lat')
        lon, lon_dir = nema.decimal_deg_to_nema_dec_min(lon_dd, 'lon')

        self.assertEqual(lat, '3647.820')
        self.assertEqual(lat_dir, 'N')
        self.assertEqual(lon, '12150.820')
        self.assertEqual(lon_dir, 'W')

        # sign flip
        lat_dd = -36.797
        lon_dd = 121.847
        lat, lat_dir = nema.decimal_deg_to_nema_dec_min(lat_dd, 'lat')
        lon, lon_dir = nema.decimal_deg_to_nema_dec_min(lon_dd, 'lon')

        self.assertEqual(lat, '3647.820')
        self.assertEqual(lat_dir, 'S')
        self.assertEqual(lon, '12150.820')
        self.assertEqual(lon_dir, 'E')

        # format leading 0
        lon_dd = -90.847
        lon, lon_dir = nema.decimal_deg_to_nema_dec_min(lon_dd, 'lon')
        self.assertEqual(lon, '09050.820')
        self.assertEqual(lon_dir, 'W')


    def test_checksum_gga(self):
        nema = NemaBase()
        gga_cksum = nema.checksum(gga_stub_data)
        self.assertEqual('{:02X}'.format(gga_cksum), gga_stub_cksum)


    def test_checksum_vtg(self):
        nema = NemaBase()
        vtg_cksum = nema.checksum(vtg_stub_data)
        self.assertEqual('{:02X}'.format(vtg_cksum), vtg_stub_cksum)


    def test_nema_wrap_gga(self):
        nema = NemaBase()
        gga = nema.wrap_nema(gga_stub_data)
        self.assertEqual(gga, gga_stub, "Failed to wrap GGA NEMA data.")


    def test_nema_wrap_vtg(self):
        nema = NemaBase()
        vtg = nema.wrap_nema(vtg_stub_data)
        self.assertEqual(vtg, vtg_stub, "Failed to wrap VTG NEMA data.")


    def test_assemble_gga(self):
        gga = NemaGGA('./test/data', cfg)

        gga.time = 1609534950.0
        gga.lat = 38.924145
        gga.lon = 94.766785
        gga.depth = -10.0

        gga_msg = gga.assemble_msg()
        gga.log_to_csv()

        self.assertEqual(gga_msg, gga_stub2, "Failed to assemble GGA NEMA sentence.")


    def test_assemble_vtg(self):
        vtg = NemaVTG('./test/data', cfg)

        vtg.time = time.time()
        vtg.heading = 309.60
        vtg.speed = 1.0

        vtg_msg = vtg.assemble_msg()
        vtg.log_to_csv()

        self.assertEqual(vtg_msg, vtg_stub2, "Failed to assemble VTG NEMA sentence.")


if __name__ == '__main__':
    unittest.main()
