#undef TEST

using System;
using System.Text;
using Microsoft.SPOT;

namespace CPF
{
    public static class uBlox
    {
        // A sample NMEA stream.
        static byte[] gpsStream = System.Text.Encoding.UTF8.GetBytes(
            "$GPRMC,045103.000,A,3014.1984,N,09749.2872,W,0.67,161.46,030913,,,A*7C\r\n" +
            "$GPGGA,045104.000,3014.1985,N,09749.2873,W,1,09,1.2,211.6,M,-22.5,M,,0000*62\r\n" +
            "$GPRMC,045200.000,A,3014.3820,N,09748.9514,W,36.88,65.02,030913,,,A*77\r\n" +
            "$GPGGA,045201.000,3014.3864,N,09748.9411,W,1,10,1.2,200.8,M,-22.5,M,,0000*6C\r\n" +
            "$GPRMC,045251.000,A,3014.4275,N,09749.0626,W,0.51,217.94,030913,,,A*7D\r\n" +
            "$GPGGA,045252.000,3014.4273,N,09749.0628,W,1,09,1.3,206.9,M,-22.5,M,,0000*6F\r\n");

        private static bool             _initialized = false;
        private static bool             _busy;
        private static Uart             _ublox;
        private static NMEA_Parser      _parser;
        private static StringBuilder    _msg;
        private static ByteString       _logMsg;
        private static ByteString       _requestHeader;
        private static ByteString       _responseHeader;
        private static ByteString       _gga;

        private static ByteString       _GGA_POLL_MSG;
        private static ByteString       _RMC_POLL_MSG;
        private static ByteString       _PBX_POLL_MSG;

        private static void WriteLog(ByteString logMessage)
        {
            _msg.Clear();
            _msg.Append(logMessage.ToString());
            EngrLogger.write(EngrLogger.ColumnNums.comment, EngrLogger.getPrefix(_msg));
        }

        private static void LogRequest(ByteString request)
        {
            _logMsg.Clear();
            _logMsg.Append(_requestHeader);
            _logMsg.Append(request);
            WriteLog(_logMsg);
        }

        private static void LogResponse(ByteString response)
        {
            _logMsg.Clear();
            _logMsg.Append(_responseHeader);
            _logMsg.Append(response);
            WriteLog(_logMsg);
        }

        public static void SendPoll(ByteString pollMsg)
        {
            LogRequest(pollMsg);
            _ublox.SendRawData(pollMsg.GetByteArray(),0, pollMsg.Length);
            _ublox.SendNewLine();
        }

        public static void PowerOn(string comPort, int baudRate = 19200)
        {
            if (!_initialized)
            {
                _ublox          = new Uart(comPort, baudRate);
                _parser         = new NMEA_Parser(GGA_MessageReceived, RMC_MessageReceived);
                _msg            = new StringBuilder();
                _logMsg         = new ByteString();
                _requestHeader  = new ByteString("Host ===> UBLOX: ");
                _responseHeader = new ByteString("Host <=== UBLOX: ");
                _GGA_POLL_MSG   = new ByteString("$EIGPQ,GGA*27");
                _RMC_POLL_MSG   = new ByteString("$EIGPQ,RMC*3A");
                _PBX_POLL_MSG   = new ByteString("$PUBX,00*33");
                _gga            = new ByteString();
                _busy           = false;
            }
        }

        public static void PowerOff()
        {
        }

        public static void RequestFix()
        {
            if (!_busy)
            {
                SendPoll(_GGA_POLL_MSG);
                _busy = true;
            }
        }

        public static void GGA_MessageReceived(ByteString msg)
        {
            LogResponse(msg);
            _gga.Clear();
            _gga.Append(msg);
            SendPoll(_RMC_POLL_MSG);
        }

        public static void RMC_MessageReceived(ByteString msg)
        {
            LogResponse(msg);
            Iridium.ReportPosition(10, 60000, Program.batteryBusVolts);
            _busy = false;
        }

        public static ByteString Last_GGA_MessageReceived()
        {
            return _gga;
        }

        public static void Parse_NMEA_Messages()
        {
#if TEST
            foreach (byte ch in gpsStream)
                _parser.Parse(ch);
#else
            while (_ublox.Available() == true)
            {
                _parser.Parse(_ublox.GetChar());
            }
#endif
        }
    }
}
