## Tracker GT02A dyegood version ... 2.3?

import logging
import asyncio
from point import Point, Path

class BlobError(Exception):
    pass

def parse_blobs(content):
    points = Path()
    for blob in content.split(b')('):
        try:
            point = parse_blob(blob)
            if point:
                points.append(point)
        except:
            logging.error("exception found while parsing blob", exc_info=True)
    return points

def parse_blob(blob):
    try:
        blob = blob.decode('ascii')
    except:
        raise BlobError("non-ascii blob: %s" % str(blob))
    if blob.startswith('028042516052BP05355228042516052'):
        blob = blob.replace('028042516052BP05355228042516052', '028042516052BR00')
    if blob.startswith('('):
        blob=blob[1:]
    if blob.endswith(')'):
        blob=blob[:-1]
    if blob == '028042516052BP00355228042516052HSO199':
        return None
    if blob.startswith('028042516052BP05355228042516052'):
        blob = blob.replace('028042516052BP05355228042516052', '028042516052BR00')
    if blob.startswith('028042516052BP'):
        raise BlobError("skipping blob: %s" % blob)
    if blob.startswith('028042516052BR00'):
        blob = blob[16:]
        ts = f"20{blob[0:2]}-{blob[2:4]}-{blob[4:6]}T{blob[33:39]}"
        ## TODO: special hack for some broken data, source file should rather be edited
        if ts == '2021-06-19T164341':
            raise BlobError(f"Wrong timestamp: {blob}")
        if ts > '2024-01-20T182700':
            import pdb; pdb.set_trace()
        try:
            lat = int(blob[7:9])+float(blob[9:16])/60
        except:
            raise BlobError("problem with blob: " + blob)
        if blob[16:17] == 'S':
            lat = -lat
        else:
            assert blob[16:17] == 'N'
        long = int(blob[17:20])+float(blob[20:27])/60
        if blob[27] == 'W':
            long = -long
        else:
            assert(blob[27:28] == 'E')
        speed_noise_heading = blob[28:45]
        speed = float(blob[28:32])/3600*1000 ## return m/s rather than km/h
        ## TODO: what's with blob[32:39]?  Extra decimals to speed?
        heading = float(blob[39:45])
        more_noise = None
        if blob[45:] != '01000000L00000000':
            more_noise = blob[45:]
            logging.error("point [%.5f, %.5f, %s] - unexpected data on position 45-: %s (we're still missing altitude?)" % (lat, long, ts, blob[45:]))
        return Point(lat, long, ts, speed, heading)
        ## TODO: should investigate
        #return Point(lat, long, ts, speed, heading, blob[32:39], more_noise)
    else:
        raise BlobError("unexpected blob: " + blob)

class Receiver:
    def __init__(self, mypos):
        self.mypos = mypos

    async def receive_blobs(self, reader, writer):
        while True:
            try:
                blob = await asyncio.wait_for(reader.readuntil(b')'), timeout=60)
                print(f"DEBUG: {blob.decode('ascii')}")
            except:
                logging.critical("exception found", exc_info=True)
                writer.close()
                break
            with open('gpstracker.raw', 'ab') as rawfile:
                rawfile.write(blob)
                rawfile.write(b'\n')
            try:
                point = parse_blob(blob)
            except:
                logging.critical("exception found", exc_info=True)
                writer.close()
                break
            if point:
                self.mypos.process_point(point)


def read_file(fn='gpstracker.raw'):
    with open(fn, 'rb') as foofile:
        content=foofile.read()
    data = parse_blobs(content)
    assert(data is not None)
    return data
