#include "gps.h"
#include "nmeaparser.h"

GPS::GPS(const char* port, int rate)
    : CommDev(port), notifyWindow(0), log(0)
{
    setRate(rate);
    SetCommWatchProc(CommProc);

    dataValid = false;
    lastTimestamp = -1;
    lastNSats = 0;
    lastLongitude = 0;
    lastLatitude = 0;
    lastVelocity = 0;
    lastCourse = 0;
}

void GPS::processString(char* str)
{
    if (log)
        fprintf(log, "COM%d: %s\n", getPort(), str);
        
    if (strstr(str, "$GPGGA") == str)
    {
        double hdop;
        int res = NMEAParser::parseGGA(str, lastTimestamp, lastLatitude, lastLongitude, lastNSats, hdop);
        dataValid = res == NMEAParser::gpsOK;
    }
    if (strstr(str, "$GPRMC") == str)
    {
        int res = NMEAParser::parseRMC(str, lastTimestamp, lastLatitude, lastLongitude, 
            lastVelocity, lastCourse);
        dataValid = res == NMEAParser::gpsOK;
    }
}

DWORD WINAPI GPS::CommProc(LPVOID lpData)
{
    DWORD dwEvtMask;
    GPS* dev = (GPS*)lpData;
    int nLength;
    char rbuff[1024];
    int rp = 0;

    if (!SetCommMask(dev->getHandle(), EV_RXCHAR))
        return (FALSE);

    while (dev->Connected()) 
    {
        dwEvtMask = 0;
        WaitCommEvent(dev->getHandle(), &dwEvtMask, NULL);
        if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR) {
            do {
                if ((nLength = dev->Read(&rbuff[rp], 1)) != 0) 
                {
                    if (rbuff[rp] == '\n') 
                    {
                        rp--;
                        rbuff[rp] = 0;
                        rp = 0;
                        
                        dev->processString(rbuff);
                        if (dev->dataValid && dev->notifyWindow != 0)
                            SendMessage(dev->notifyWindow, WM_GPS, 0, 0);
                    } 
                    else
                        rp++;
                }
            } while (nLength > 0);
        }
    }

    dev->ClearWatch();

    return true;
}

