using System;
using System.IO.Ports;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.SPOT;
using System.Threading;
using HWModules;
using SWModules;

namespace CPFUnitTests
{
    [TestClass]
    public class UnitTestIridiumRudicsRoboCaller
    {

        /// <summary>
        /// Test to just call and broadcast a counter during login
        ///
        /// This was prototyped in a python notebook 201904
        /// </summary>
        /// 
       
        private static int utcount;
        [TestMethod]
        public void TestIridiumRudicsRoboCaller()
        {
            Init();
            int resp = 0;
            bool carrier = false;

            mother.DisableChannelPower(MotherBoard.ChannelNames.BluetoothChannel);

            imodem.ReleaseDataHandler();

            imodem.IOPort.DataReceived += dataReceived;
            //Connect
            var state = 0;
            var inState = 0;
            var broadcast = 0;
            var stateEntry = true;
            var outStr = new StringBuilder(32);

            while (true)
            {
                //waitforanyresponse
                Thread.Sleep(1000);
                mother.ToggleDebugLED();

                if (gotMsg)
                {

                    if (gotOk)
                    {
                        Debug.Print("RXD OK");
                    }

                    if (gotNoCarrier)
                    {
                        Debug.Print("RXD NO CARRIER");
                        state = 2;
                        stateEntry = true;
                    }

                    if (gotBusy)
                    {
                        Debug.Print("RXD BUSY");
                        state = 2;
                        stateEntry = true;
                    }

                    if (gotConnect)
                    {
                        Debug.Print("RXD CONNECTED");
                        state = 4;
                        broadcast = 0;
                        stateEntry = true;
                    }

                    if (gotCsq)
                    {
                        Debug.Print("RXD CSQ");
                        state = 3;
                        stateEntry = true;
                    }
                    gotMsg = false;
                    gotOk = false;
                    gotCsq = false;
                    gotBusy = false;
                    gotNoCarrier = false;
                    gotConnect = false;
                }



                switch (state)
                {
                    // Send No Echo
                    case 0:
                        Debug.Print("SEND ATEN");
                        imodem.sendNoEcho();
                        state++;
                        continue;
                    // Set call service bearer type
                    case 1:
                        Debug.Print("SEND CBST");
                        imodem.SelectBearerServiceType(NAL_A3LAR.CallSpeed.BPS2400V110);
                        state++;
                        continue;
                    // query csq
                    case 2:
                        if (stateEntry)
                        {
                            Debug.Print("SEND CSQ");
                            imodem.sendCSQ();
                            stateEntry = false;
                            inState = 0;
                        }
                        else
                        {
                            inState++;
                            if (inState == 10)
                                stateEntry = true;
                        }

                        continue;
                    // Make the call
                    case 3:
                        if (stateEntry)
                        {
                            Thread.Sleep(1000);
                            Debug.Print("DIALING");
                            imodem.dialDefaultRudics();
                            stateEntry = false;
                        }

                        continue;

                    // Send a message while connected
                    case 4:
                        if (stateEntry)
                        {
                            Debug.Print("TXD BROADCAST");
                            stateEntry = false;
                            inState = 0;
                            outStr.Clear().Append("broadcast I am number ").Append(broadcast++).Append("\r");
                            var outMsg = Encoding.UTF8.GetBytes(outStr.ToString());
                            imodem.IOPort.Write(outMsg, 0, outMsg.Length);
                        }
                        else
                        {
                            inState++;
                            if (inState == 10)
                                stateEntry = true;
                        }

                        continue;

                }
            }
        }


        private static MessageQueue messageQueue;
        private static IridiumModem1 imodem;
        private static MotherBoard mother;

        static bool runonce = false;
        public void Init()
        {
            if (!runonce)
            {
                imodem = IridiumModem1.Instance;
                mother = MotherBoard.Instance;
                mother.EnableChannelPower(MotherBoard.ChannelNames.IridiumChannel);
                messageQueue = MessageQueue.Instance;
                runonce = true;
                //EngrLogger.Comment("Initializing Iridium Modem");
                imodem.simpleInit();
                imodem.powerUp();
            }
        }


        private bool gotMsg, gotOk, gotConnect, gotCsq, gotNoCarrier, gotBusy;
        private byte[] buffer = new byte[1024];
        private byte[] message = new byte[1024];
      
        private int midx = 0;

        public void dataReceived(object sender, SerialDataReceivedEventArgs e) //TODO P2 need several unit tests
        {
            //readuntil
            //
            int bytesRead = 0;
            var msg = new StringBuilder(128);
            try
            {
                bytesRead = imodem.IOPort.Read(buffer, 0, imodem.IOPort.BytesToRead);
            }
            catch
            {
                Debug.Print("Imodem Read Error");
            }

            gotMsg = true;
            //process the buffer
            for (int i = 0; i < bytesRead; i++)
            {
                if (buffer[i] == 10)
                    continue;
                message[midx++] = buffer[i];
                if (buffer[i] == '\r')
                {

                    //Process
                    msg.Clear().Append(SafeEncoding.GetChars(message, 0, midx-1));
                    Debug.Print("GOT: "+msg);
                    gotMsg = true;
                    gotOk = String.Equals(msg.ToString(), "OK") || gotOk;
                    gotConnect = String.Equals(msg.ToString(), "CONNECT 19200") || gotConnect;
                    gotNoCarrier = String.Equals(msg.ToString(), "NO CARRIER") || gotNoCarrier;
                    gotBusy = String.Equals(msg.ToString(), "BUSY") || gotBusy;
                    if (midx > 5) gotCsq = String.Equals(msg.ToString().Substring(0, 5), "+CSQ:") || gotCsq;
                    midx = 0;
                }
            }
        }
    }
}
