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

namespace CPFUnitTests
{
    [TestClass]
    public class UnitTestIridiumRUDICS
    {

        /// <summary>
        /// Test zmodem send using the bluetooth serial port, but plug it into a linux tty login.
        /// if no login is provided, the attempt should fail gracefully. 
        /// </summary>
        /// 

        private static int utcount;
        [TestMethod]
        public void TestIridium_BidirectionalTransfer()
        {
            Init();
            int resp = 0;
            bool carrier = false;

            IridiumPosixSession session = new IridiumPosixSession(imodem);

            session.Username = "cpfloat";
            session.Password = "mbari!@!123";
            session.LoginPrompt = "login:";
            session.PasswordPrompt = "Password:";
            session.CommandPrompt = "$ ";
            utcount++;

            //Connect

            Thread.Sleep(1000); // enough time for the cbst message to come in
            imodem.sendNoEcho();
            Thread.Sleep(1000); // enough time for the cbst message to come in
            imodem.SelectBearerServiceType(NAL_A3LAR.CallSpeed.BPS1200V110);
            Thread.Sleep(1000); // enough time for the cbst message to come in
            messageQueue.processQMaxLimit();


            imodem.sendCSQ();
            Thread.Sleep(10000); // enough time for the cbst message to come in
            mother.ToggleDebugLED();
            messageQueue.processQMaxLimit();

            EngrLogger.Comment("Done Setup");

            byte[] baRUDICSnumber;
            baRUDICSnumber = Encoding.UTF8.GetBytes(@"00881600005391");
            EngrLogger.Comment("Session Dialing");

            // Blocks waiting for connection. 
            var try_count = 5;
            do
            {
                resp = session.Connect(baRUDICSnumber);
                if (resp < 0 && --try_count == 0) goto failed;
                if (resp < 0) Thread.Sleep(1000);
            } while (resp != 0);


            carrier = true;

            //Login
            resp = session.Login();
            if (resp == (int)PosixSession.ERROR.NOCARRIER) {
                EngrLogger.Comment("PS002 Login Failed: Connection Dropped");
                carrier = false;
                goto failed;
            }

            if (resp == (int)PosixSession.ERROR.NOLOGIN) {
                EngrLogger.Comment("PS003 Login Failed: No login received.");
                goto failed;
            }

            {
                //Send a Message to Broadcast
                StringBuilder utmsg = new StringBuilder("I am UNIT TEST #: ");
                utmsg.Append(utcount.ToString());
                utmsg.Append(" MSG: ");
                EngrLogger.Comment("PS004 Broadcasting: " + utmsg.ToString());
                session.Broadcast(utmsg.ToString());
                Thread.Sleep(1000);
            }

            //Send Files
            {
                var files = new Queue();

                files.Enqueue(@"\SD\data\cpf001.001.2019-3-7T19-22-37.dura");
                files.Enqueue(@"\SD\data\cpf001.001.2019-3-7T19-22-37.log");
                files.Enqueue(@"\SD\data\cpf001.001.2019-3-7T19-22-37.eng");
                files.Enqueue(@"\SD\data\cpf001.001.2019-3-7T19-22-37.msg");
                files.Enqueue(@"\SD\data\cpf001.001.2019-3-7T19-22-37.isus");

                while (files.Count > 0) {
                    var fname = (string)files.Dequeue();
                    var tries = 0;
                    var max_tries = 2;
                    do
                    {
                        if (!session.WaitForPrompt()) goto failed;
                        resp = session.ZModemSendTransaction(fname);
                    } while (resp != 0 && --max_tries > 0);


                }
            }
            if (resp == 0) goto done;

        /*
                    //Receive File

                    //Delete Local File 
                    try {
                        if (File.Exists("\\SD\\manifest.txt"))
                            File.Delete("\\SD\\manifest.txt");
                    }
                    catch {
                        goto done;
                    }

                    resp = session.CheckForPrompt();
                    if (resp == 0) goto done;

                    resp = session.ZModemReceiveTransaction("/home/rawa/manifest.txt", "\\SD\\");
                    if (resp == 0) goto done;
        */
        done:
            //Logout
            session.Logout();
        failed:
            //Shut down the session.
            session.Disconnect();

            // Hang up the call
            bool bRUDICSThreadRunning = true;

            if (!carrier)
                return;

            bool bEscapeReceived = false;
            int iAttempts = 0;
            while (bRUDICSThreadRunning && iAttempts < 10) {
                messageQueue.processQ();

                if (!bEscapeReceived)
                    resp = imodem.waitForResponse(NAL_A3LAR.commands.escapeSeq);
                else
                    resp = imodem.waitForResponse(NAL_A3LAR.commands.chup);
                if (resp == 0) {
                    Thread.Sleep(10);
                    continue;
                }
                else if (resp == 1) {
                    EngrLogger.Comment("Response from IModem");
                    bRUDICSThreadRunning = false;
                    if (!bEscapeReceived)
                        bEscapeReceived = true;
                    else
                        bRUDICSThreadRunning = false;
                }
                else {
                    EngrLogger.Comment("No Reponse from IModem");
                    bEscapeReceived =
                        true; //this will automatically alternate which messsage is sent. Sometimes the connection is dropp and the +++ doesn't return an OK
                    iAttempts++;
                }
            }

            if (iAttempts == 10) Assert.Fail();

            for (int i = 0; i < 6; i++) {
                EngrLogger.Comment("Cleanup: " + i.ToString());
                messageQueue.processQ();
                Thread.Sleep(1000);
            }



        }

        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();
            }
        }
    }
}
