using System;
using System.IO;
using System.IO.Ports;
using System.Reflection;
using System.Text;
using GHI.IO.Storage;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using Microsoft.SPOT.IO;
using SWModules;
using Zmodem;

namespace HWModules
{
    class Console
    {
        // Constants
        private const bool GC_LOCALECHO = true;
        private const byte GC_MAXTOKENS = 10;
        // Limits of FAT32 Filesystems
        //private const int GC_MAXFILES = 125;
        private const byte GC_MAXFILEN = 0xFF;
        private const int GC_MAXPATHL = 0xFFF;

        private char[] GC_DELIMITERS = new char[] { ' ', ',' };
        public enum CMD
        {
            HELP,
            PWD,
            DIR,
            CD,
            MKDIR,
            CP,
            RM,
            MV,
            SZ,
            RZ,
            UT,
            COM,
            REBOOT,
            POW,
            DATE,
            SET,
            CPF,
            UNKNOWN,
        };

        private enum UT
        {
            Console,
            ZmodemConsole,
            EngLogger,
            Iridium,
            Rudics,
            Ctd,
            Optode,
            Pump,
            Pth,
            Elmo,
            Gps,
            Watchdog,
            EMonBatt,
            EMonPump,
            Msc,
            Unknown,
        };

        private enum PORT
        {
            COM2,
            COM3,
            COM4,
            COM5,
            COM6,
            COM7,
            COM8,
            COM9,
            COM10,
            COM11,
            COM12,
            Unknown
        };

        // IO 
        private SerialPort sPort;
        private SerialPort comPort;
        private I2CSerialPort i2cComport;
        private bool isI2cPort;
        private MotherBoard _mb;
        private StringBuilder sbTemp = new StringBuilder(GC_MAXMESSAGESIZE);
        private MessageQueue _messageQueue;
        private QRecord _msgQEntry;

        // SD CARD
        private SDCard sdCard;
        private VolumeInfo viSDCard;

        // SerialPort BUFFER
        private const int GC_MAXMESSAGESIZE = 0xFFF;
        private StringBuilder sbInput = new StringBuilder(GC_MAXMESSAGESIZE);
        private byte[] txbuff;
        private byte[] rxbuff;
        private int rxbuffpos;
        int bytesAvailable;

        // Program Mode
        public CMD modeCMD { get; protected set; }

        //CommandParser
        private string[] cmdtok = new string[GC_MAXTOKENS];

        //Directory buffers
        //private string[] dirbuff = new string[GC_MAXFILES];
        private StringBuilder srcdir = new StringBuilder(GC_MAXPATHL);
        private StringBuilder desdir = new StringBuilder(GC_MAXPATHL);
        private StringBuilder pwDir = new StringBuilder(GC_MAXPATHL);

        public Console(SerialPort port)
        {
            modeCMD = CMD.UNKNOWN;

            sPort = port;
            txbuff = new byte[GC_MAXMESSAGESIZE];
            rxbuff = new byte[GC_MAXMESSAGESIZE];
            _mb = HWModules.MotherBoard.Instance;
            rxbuffpos = 0;
            sPort.Open();

            // SD Card init
            try
            {
                viSDCard = new VolumeInfo("\\SD");
            }
            catch (Exception e)
            {
                ////TODO P2 Error here.
                Debug.Print("Can't Load SDCard:" + e.ToString());
            }

            pwDir.Clear();
            pwDir.Append(viSDCard.RootDirectory);

            _messageQueue = MessageQueue.Instance;
//           _msgQEntry = new QRecord(ProcessMessage);

        }

//        public void welcomeMessage()
//        {
//            Assembly asm = Assembly.GetExecutingAssembly();
//            writeLine("\r\nCoastal Profiling Float Console \r\n" +
//                      "Assembly: " +
//                      asm.FullName +
//                      "\r\n\r");

//        }

//        public void printPrompt()
//        {
//            txbuff = Encoding.UTF8.GetBytes("\n\rCPF>");
//            sPort.Write(txbuff, 0, txbuff.Length);
//        }

//        public void read()
//        {
//            bytesAvailable = sPort.BytesToRead;
//            if (bytesAvailable > 0)
//            {
//                sPort.Read(rxbuff, rxbuffpos, 1);
//                if (GC_LOCALECHO)
//                    sPort.Write(rxbuff, rxbuffpos, 1); //echo the character
//                rxbuffpos++;
//            }
//            else
//                return;

//            if (rxbuff[rxbuffpos - 1] == '\r' ||
//                rxbuff[rxbuffpos - 1] == '\n')
//            {
//                this.gotCommand();
//            }
//        }

//        public void readUntilLN()
//        {
//            bytesAvailable = sPort.BytesToRead;

//            if (bytesAvailable <= 0)
//                return;

//            for (int i = 0; i < bytesAvailable; i++)
//            {
//                sPort.Read(rxbuff, rxbuffpos, 1);
//                if (GC_LOCALECHO)
//                {
//                    sPort.Write(rxbuff, rxbuffpos, 1);
//                }
                
//                // If we are in a serial Port command program
//                if (modeCMD == CMD.COM)
//                {
//                    try
//                    {
//                        if (rxbuff[rxbuffpos] == 0x03) //ETX CTRL-C Received
//                        {
//                            writeLine("CTRL-C Received, exiting program...\r\n\r");
//                            modeCMD = CMD.UNKNOWN;
//                            if (isI2cPort)
//                                i2cComport.Close();
//                            else
//                                comPort.Close();
//                        }
//                        else
//                            if (isI2cPort)
//                                i2cComport.WriteByte(rxbuff[rxbuffpos]);
//                            else
//                                comPort.WriteByte(rxbuff[rxbuffpos]);

//                        return;
//                    }
//                    catch
//                    {
//                        writeLine("Error writing to com port, exiting com program.\r\n");
//                        if (isI2cPort)
//                            i2cComport.Close();
//                        else 
//                            comPort.Close();
//                        modeCMD = CMD.UNKNOWN;
//                        return;
//                    }
                    
//                }
                
//                rxbuffpos++; //enable backspace functionality. 

//                if (rxbuff[rxbuffpos - 1] == '\b')
//                {
//                    rxbuffpos -= 2;
//                    if (rxbuffpos < 0) rxbuffpos = 0;
//                    sPort.WriteByte(32); sPort.WriteByte(8);
//                    continue;
//                }

//                if ((rxbuff[rxbuffpos - 1] == '\r' ||
//                    rxbuff[rxbuffpos - 1] == '\n'))
//                {
//                    this.gotCommand();
//                }

//            }
//        }

//        public void writeLine(string s)
//        {
//            txbuff = Encoding.UTF8.GetBytes(s);
//            sPort.Write(txbuff, 0, txbuff.Length);
//        }

//        public void writeLine(StringBuilder s)
//        {
//            writeLine(s.ToString());
//        }

//        // BUFFER COMMANDS TODO MOVE TO SUBCLASS
//        public void gotCommand()
//        {
//            // Test for Case in rcving \r\n from the console
//            if (rxbuffpos == 1)
//            {
//                rxbuffpos = 0;
//                Array.Clear(rxbuff, 0, rxbuff.Length);
//                writeLine("\r"); printPrompt();
//                return;
//            }

//            //else


//            sbInput.Clear();
//            try
//            {
//                sbInput.Append(SafeEncoding.GetChars(rxbuff, 0, rxbuffpos - 1));
//                Debug.Print("GOT LINE: " + sbInput.ToString());

//                this.ProcessCommand();

//            }
//            catch
//            {
//                // ignored
//            }

//            rxbuffpos = 0;
//            Array.Clear(rxbuff, 0, rxbuff.Length);
//        }

//        public void ProcessMessage(QRecord qRecord)
//        {
//            //TODO P5 copy the message and call ProcessCommand?
//        }

//        private void ProcessCommand()
//        {
//            CMD cmd = CMD.UNKNOWN;
//            byte itok = 0;

//            Array.Clear(cmdtok, 0, cmdtok.Length);
//            cmdtok = sbInput.ToString().Trim().Split(GC_DELIMITERS, (int)GC_MAXTOKENS);

//            //Decode Command
//            cmd = decodeCommand(cmdtok[0]);

//            //Output to DEBUG
//            foreach (var s in cmdtok)
//            {
//                if (itok == 0)
//                    continue;

//                Debug.Print("GOT TOK: " + s);
//                itok++;
//            }

//            writeLine("\r\n");

//            switch (cmd)
//            {
//                case CMD.HELP:
//                    printHelp();
//                    break;
//                case CMD.PWD:
//                    presentWorkingDirectory();
//                    break;
//                case CMD.DIR:
//                    dir();
//                    break;
//                case CMD.CD:
//                    cd();
//                    break;
//                case CMD.MKDIR:
//                    mkdir();
//                    break;
//                case CMD.CP:
//                    cpormv(CMD.CP);
//                    break;
//                case CMD.RM:
//                    rm();
//                    break;
//                case CMD.MV:
//                    cpormv(CMD.MV);
//                    break;
//                case CMD.SZ:
//                    sz();
//                    break;
//                case CMD.RZ:
//                    rz();
//                    break;
//                case CMD.UT:
//                    ut();
//                    break;
//                case CMD.COM:
//                    com();
//                    break;
//                case CMD.POW:
//#if GEN2
//                    pow();
//#else
//                    writeLine("Incompatible command\r\n");
//#endif
//                    break;
//                case CMD.REBOOT:
//                    reboot();
//                    break;
//                case CMD.DATE:
//                    date();
//                    break;
//                case CMD.SET:
//                    changeSetting();
//                    break;
//                case CMD.CPF:
//                    cpfChange();
//                    break;
//                case CMD.UNKNOWN:
//                    writeLine("ERROR: Unknown CMD\r\n");
//                    break;

//            }
//            //at end print out new prompt
//            printPrompt();
//        }

//        private void cpfChange()
//        {
//            if (cmdtok.Length < 2)
//            {
//                writeLine("usage: cpf <action> \r\n"+
//                          "\t Actions: \r\n"+
//                          "\t   GO: Start profiling operations\r\n"+
//                          "\t   RECOVERYTRUE: Enable recovery mode\r\n"+
//                          "\t   RECOVERYFALSE: Disable recovery mode\r\n"+
//                          "\t   STARTDOG: Start watchdog timer\r\n"+
//                          "\t   FAKEMTSBD: Send fase MTSBD using Iridium\r\n"+
//                          "\t   EXIT: Halt state machine\r\n");
//                return;
//            }

//            switch (cmdtok[1].ToLower())
//            {
//                case "go":
//                    SV.SurfaceOpsGo = true;
//                    break;
//                case "recoverytrue":
//                    SV.RecoveryMode = true;
//                    EngrLogger.writeToColumns("Recovery mode set true");
//                    break;
//                case "recoveryfalse":
//                    SV.RecoveryMode = false;
//                    EngrLogger.writeToColumns("Recovery mode set false");
//                    break;
//                case "startdog":
//                    WatchDog.startWatchdog();
//                    EngrLogger.writeToColumns("Starting watchdog");
//                    break;
//                case "fakemtsbd":
//                    NAL_A3LAR.fakeMTSBD();
//                    break;
//                case "exit":
//                    SV.CurrentState = CPFStates.exit;
////                    EngrLogger.CurrentState = cpfStatesArray[(int)SV.CurrentState].stateName;
//                    break;
//                default:
//                    writeLine("ERROR: Unknown cpf action requested");
//                    break;
//            }

//        }

//        private void changeSetting()
//        {
//            if (cmdtok.Length < 3)
//            {
//                writeLine("usage: set <field> <value>\r\n");
//                return;
//            }

//            // Parse field
//            double argValue = -1;
//            try
//            {
//                argValue = double.Parse(cmdtok[2]);
//            }
//            catch
//            {
//                writeLine("ERROR: Cannot parse setting field.\r\n");
//            }

//            // Field name
//            switch (cmdtok[1].ToLower())
//            {
//                case "simp":
//                    // TODO P2 do we use this?
//                    break;
//                case "upengr":
//                    SV.UploadEngrFile = true;
//                    break;
//                case "maxprofiles":
//                    if ((int) argValue <= 0 || (int) argValue >= 200)
//                    {
//                        writeLine("ERROR: Invalid profile setting\r\n");
//                        return;
//                    }

//                    SV.MaxProfiles = (int) argValue;
//                    sbTemp.Clear().Append("Setting Max Number of Profiles to: ").Append(SV.MaxProfiles);
//                    EngrLogger.writeToColumns(sbTemp);
//                    break;

//                case "missiontimeout":
//                    if ((int) argValue <= 0 || (int) argValue >= 120)
//                    {
//                        writeLine("ERROR: Invalid mission timeout");
//                        return;
//                    }

//                    SV.MissionTimeoutTS = new TimeSpan(0, (int) argValue, 0, 0);
//                    SV.MissionTimedOut = false;
//                    sbTemp.Clear().Append("Set MissionTimeout hours to: ").Append(SV.MissionTimeoutTS);
//                    EngrLogger.writeToColumns(sbTemp);
//                    break;

//                case "parktime":
//                    if ((int) argValue <= 0 || (int) argValue >= 172800) //2*24*3600
//                    {
//                        writeLine("ERROR: Invalid park time\r\n");
//                        return;
//                    }
                    
//                    Mission.descendTable[0].parkTime = new TimeSpan(0, 0, (int)argValue, 0);
//                    sbTemp.Clear().Append("Park time minutes to: ");
//                    sbTemp.Append(Mission.descendTable[0].parkTime);
//                    EngrLogger.writeToColumns(sbTemp);
//                    break;

//                case "parkpressure":
//                    if ((float) argValue <= 4 || (float) argValue >= 300)
//                    {
//                        writeLine("ERROR: Invalid park pressure\r\n");
//                        return;
//                    }

//                    Mission.descendTable[9].pressure = (float) argValue;
//                    sbTemp.Clear().Append("Setting Park Pressure to: ");
//                    sbTemp.Append(Mission.descendTable[0].pressure);
//                    EngrLogger.writeToColumns(sbTemp);
//                    break;

//                default:
//                    writeLine("ERROR: Unknown field.\r\n");
//                    break;
//            }

//        }

//        private void date()
//        {
//            if (cmdtok.Length < 7)
//            {
//                writeLine(DateTime.Now.ToString());
//                writeLine("usage: date <year> <month> <day> <hour> <minute> <second> [NUMERIC]");
//                return;
//            }

//            int year   = int.Parse(cmdtok[1]);
//            int month  = int.Parse(cmdtok[2]);
//            int day    = int.Parse(cmdtok[3]);
//            int hour   = int.Parse(cmdtok[4]);
//            int minute = int.Parse(cmdtok[5]);
//            int second = int.Parse(cmdtok[6]);


//            Utility.SetLocalTime(new DateTime(year,month,day,hour,minute,second));
//            EngrLogger.openNewFile();
//        }

//        private void pow()
//        {
//            int channel = -1;
//            if (cmdtok.Length < 3)
//            {
//                writeLine("usage: pow <channel [1..15] [16=pump]> <on/off>");
//                for (int i = 1; i <= 16; i++)
//                {
//                    writeLine("CH"+i+":"+_mb.QueryChannelPower(i)+"\r\n");
//                }
//                return;
//            }

//            //channel number
//            try
//            {
//                channel = int.Parse(cmdtok[1]);
//                if (channel < 1 || channel >16)
//                    throw new ArgumentOutOfRangeException();
//            }
//            catch
//            { writeLine("Invalid channel number: "+cmdtok[1]+"\r\n"); return; }

//            //state
//            if (string.Equals("on", cmdtok[2]))
//            {
//                if (channel <16)
//                    _mb.EnableChannelPower(channel);
//                else
//                    _mb.EnablePump();
//            }
//            else if (string.Equals("off", cmdtok[2]))
//            {
//                if (channel <16)
//                    _mb.DisableChannelPower(channel);
//                else 
//                    _mb.DisablePump();
//            }

//        }

//        private void com()
//        {
//            if (cmdtok.Length < 2)
//            {
//                writeLine("usage: com <portnum [2-12]> <baudrate> <databits 8/7/6/5> <parity O/E/N/M/S> <stopbits 1/1.5/2/0>\r\n" +
//                          "\t defaults are 9600 8 N 1");
//                return;
//            }

//            //Set Defaults
//            int portnum = 2;
//            int baud = 9600;
//            int databits = 8;
//            Parity parity = Parity.None;
//            StopBits stopbits = StopBits.One;

//            if (!ParseSerialConfig(ref portnum, ref baud, ref databits, ref parity)) return;

//            //For traditional serialports
//            if (portnum <= 6)
//            {
//                try
//                {
//                    comPort = new SerialPort("COM" + portnum.ToString(), baud, parity, databits, stopbits);
//                    comPort.Open();
//                    comPort.DataReceived += ComPortOnDataReceived;
//                    isI2cPort = false;

//                }
//                catch (Exception e)
//                {
//                    writeLine("Error Opening SerialPort " + portnum.ToString() + ":" + e.ToString());
//                    return;
//                }
//            }
//            //For i2c ports (slots 3-6)
//            if (portnum > 6)
//            {
//                i2cComport = new I2CSerialPort("COM" + portnum.ToString(), baud, databits, parity, stopbits);
//                i2cComport.Open();
//                i2cComport.DataReceived += I2CPortOnDataReceived;
//                isI2cPort = true;
//            }
            
//            writeLine("Serial Port Connected, press CTRL-C to exit program...\r\n\r");

//            modeCMD = CMD.COM;


//        }

//        private void I2CPortOnDataReceived(object sender, EventArgs e)
//        {
//            int bytesToRead = i2cComport.BytesToRead;
//            int inChar;
//            if (bytesToRead == 0)
//                return;
//            for (int i = 0; i < bytesToRead; ++i)
//            {
//                inChar = i2cComport.ReadByte();
//                if (inChar == -1)
//                    return;
//                sPort.WriteByte((byte) inChar);
//            }
//        }

//        private void ComPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
//        {
//            int bytesToRead = comPort.BytesToRead;
//            int inChar;
//            if (bytesToRead == 0)
//                return;
//            for (int i = 0; i < bytesToRead; ++i)
//            {
//                inChar = comPort.ReadByte();
//                if (inChar == -1)
//                    return;
//                sPort.WriteByte((byte) inChar);
//            }

//        }

//        private bool ParseSerialConfig(ref int portnum, ref int baud, ref int databits, ref Parity parity)
//        {
//            StopBits stopbits;
//            for (int i = 1; i < cmdtok.Length; ++i)
//            {
//                switch (i)
//                {
//                    case 1: //portnum
//                        try
//                        {
//                            portnum = int.Parse(cmdtok[1]);
//                            if (string.Equals("COM"+portnum.ToString(), sPort.PortName) ||
//                                portnum < 1 || portnum > 12)
//                                throw new ArgumentOutOfRangeException("invalid portnum");
//                        }
//                        catch
//                        {
//                            writeLine("Invalid Portnum Specified " + cmdtok[1] + "\r\n");
//                            return false;
//                        }

//                        break;
//                    case 2: //baudrate
//                        try
//                        {
//                            baud = int.Parse(cmdtok[2]);
//                        }
//                        catch
//                        {
//                            writeLine("Invalid Baud Rate Specified: " + cmdtok[2] + "\r\n");
//                            return false;
//                        }
//                        break;
//                    case 3: //databits
//                        try
//                        {
//                            databits = int.Parse(cmdtok[3]);
//                            if (databits < 5 || databits > 8)
//                                throw new ArgumentOutOfRangeException("invalid databits");
//                        }
//                        catch
//                        {
//                            writeLine("Invalid Databits Specified: " + cmdtok[3] + "\r\n");
//                            return false;
//                        }
//                        break;
//                    case 4: //parity
//                        try
//                        {
//                            if (string.Equals(cmdtok[4].ToLower(), "n"))
//                                parity = Parity.None;
//                            else if (string.Equals(cmdtok[4].ToLower(), "e"))
//                                parity = Parity.Even;
//                            else if (string.Equals(cmdtok[4].ToLower(), "o"))
//                                parity = Parity.Odd;
//                            else if (string.Equals(cmdtok[4].ToLower(), "m"))
//                                parity = Parity.Mark;
//                            else if (string.Equals(cmdtok[4].ToLower(), "s"))
//                                parity = Parity.Space;
//                            else
//                                throw new ArgumentOutOfRangeException("Invalid parity");
//                        }
//                        catch
//                        {
//                            writeLine("Invalid Parity Specified: " + cmdtok[4] + "\r\n");
//                            return false;
//                        }
//                        break;
//                    case 5: //stopbits
//                        try
//                        {
//                            double dStopbits = double.Parse(cmdtok[5]);
//                            if (dStopbits == 1)
//                                stopbits = StopBits.One;
//                            else if (dStopbits == 1.5)
//                                stopbits = StopBits.OnePointFive;
//                            else if (dStopbits == 2)
//                                stopbits = StopBits.Two;
//                            else if (dStopbits == 0)
//                                stopbits = StopBits.None;
//                            else
//                                throw new ArgumentOutOfRangeException("Invalid stopbits");
//                        }
//                        catch
//                        {
//                            writeLine("Invalid Stopbits Specified: " + cmdtok[5] + "\r\n");
//                            return false;
//                        }
//                        break;
//                }
//            }
//            return true;
//        }

//        private void mkdir()
//        {
//            DirectoryInfo dinfo;
//            if (cmdtok.Length < 2)
//            {
//                writeLine("usage: mkdir <dir>\r\n");
//                return;
//            }

//            changeWorkingDir(ref desdir, 1);

//            try
//            {
//                if (Directory.Exists(desdir.ToString()))
//                {
//                    writeLine("ERROR: directory already exists.\r\n");
//                    return;
//                }
//                dinfo = Directory.CreateDirectory(desdir.ToString());
//                if (dinfo == null)
//                {
//                    writeLine("ERROR: directory creation failed.\r\n");
//                    return;
//                }
//            }
//            catch
//            {
//                writeLine("ERROR: directory creation failed.\r\n");
//                return;
//            }

//            writeLine("Directory successfully created at " + dinfo.CreationTimeUtc.ToString() + "\r\n");

//        }

//        private void rm()
//        {
//            int sarg = 0;

//            if (cmdtok.Length < 2)
//            {
//                writeLine("usage: rm <file> or rm -f <dir>\r\n");
//                return;
//            }

//            sarg = (cmdtok[1][0] == '-') ? 1 : 0;

//            //change input to full path
//            changeWorkingDir(ref srcdir, 1 + sarg);

//            try
//            {
//                if (!File.Exists(srcdir.ToString()) && !Directory.Exists(srcdir.ToString()))
//                {
//                    writeLine("ERROR: file/dir does not exist\r\n");
//                    return;
//                }
//            }
//            catch
//            {
//                writeLine("ERROR: file/dir does not exist\r\n");
//                return;
//            }

//            //delete file
//            if (sarg == 0)
//            {
//                try
//                {
//                    File.Delete(srcdir.ToString());
//                }
//                catch
//                {
//                    writeLine("ERROR: File delete failed.\r\n");
//                    return;
//                }
//                writeLine("File(s) deleted.\r\n");
//            }
//            else if (sarg == 1)
//            {
//                try
//                {
//                    Directory.Delete(srcdir.ToString());
//                }
//                catch
//                {
//                    writeLine("ERROR: Directory delete failed.\r\n");
//                    return;
//                }
//                writeLine("Directory deleted. \r\n");
//            }


//        }
//        private void rz()
//        {
//            writeLine("Beginning Zmodem Receive.\r\n");
//            ZmodemReceiver zr = new ZmodemReceiver(sPort, false);

//            zr.filePrefix = "\\SD\\";
//            int ret = 0;
//            do
//            {
//                ret = zr.doTasks();
//            } while (ret == 0);
//        }
//        private void sz()
//        {
//            if (cmdtok.Length < 2)
//            {
//                writeLine("usage sz <srcfile>\r\n");
//                return;
//            }

//            changeWorkingDir(ref srcdir, 1);

//            try
//            {
//                if (File.Exists(srcdir.ToString()) == false)
//                {
//                    writeLine("ERROR: No such source file.\r\n");
//                    return;
//                }
//            }
//            catch
//            {
//                writeLine("ERROR: No such source file.\r\n");
//                return;
//            }

//            //Ok, we can try to conduct a ZMODEM interaction...
//            ZmodemSender zs = new ZmodemSender(sPort, srcdir.ToString());

//            //it will eventually give up or finish... single file at this point. 
//            int ret = 0;
//            do
//            {
//                ret = zs.doTasks();
//            } while (ret == 0);


//            writeLine("Zmodem Finished, result code"+ret+"\r\n");
//        }

//        private void reboot()
//        {
//            PowerState.RebootDevice(false);
//        }

//        private void ut()
//        {
//            if (cmdtok.Length < 2)
//            {
//                writeLine("usage ut <utname> <numattempts>\r\n");
//                writeLine("\t available options are: \r\n" +
//                          "\t\t console \t- simple console print and read tests\r\n" +
//                          "\t\t zmodem  \t- test zmodem send and receive.\r\n" +
//                          "\t\t englogger \t- test some write commands to the engrlogger\r\n" +
//                          "\t\t iridium \t- test iridium driver functions except for rudics\r\n" +
//                          "\t\t rudics \t- test iridium drivers for full rudics connections to the main server\r\n" +
//                          "\t\t ctd \t- test the seabird 41 drivers\r\n" +
//                          "\t\t optode \t- optode driver test\r\n" +
//                          "\t\t gps \t- test the GPS and driver\r\n" +
//                          "\t\t pump \t- test the elmo driver\r\n" +
//                          "\t\t pth \t- test pressure temp and humid sensor\r\n" +
//                          "\t\t msc \t- test MBARI multi-sensor controller\r\n" +
//                          "\t\t elmo \t- test gps drivers\r\n" +
//                          "\t\t energymonbatt \t- test energy monitors on the battery\r\n" +
//                          "\t\t energymonpump \t- test energy monitor on the pump\r\n" +
//                          "\t\t watchdog \t- test the watchdog\r\n");

//                return;
//            }

//            int nattempts = 1;
//            int natt;
//            if (cmdtok.Length == 3)
//            {
//                try { natt = int.Parse(cmdtok[2]); }
//                catch { 
//                    writeLine("Bad Input, try again \n\r");
//                    return;
//                }

//                if (natt > 1)
//                {
//                    nattempts = natt;
//                }
//            }

//            for (int i = 0; i < nattempts; i++)
//            {
//                switch (DecodeUnitTest(cmdtok[1]))
//                {
//                    case UT.Console:
//                        writeLine("Running Bluetooth Console Unit Test\n\r");
//                        //TestManager.RunTest(typeof(UnitTestBTConsole));
//                        break;
//                    case UT.ZmodemConsole:
//                        // todo P3 don't really need this either, we can just try zmodeming
//                        break;
//                    case UT.Ctd:
//                        //TODO P3 unimplemented
//                        break;
//                    case UT.Elmo:
//                        //TODO P3 unimplemented
//                        break;
//                    case UT.Gps:
//                        writeLine("Running GPS Unit Test\r\n");
//                        //TestManager.RunTest(typeof(UnitTest_MotherBoard_GPS));
//                        break;
//                    case UT.Optode:
//                        //TODO P3 unimplemented
//                        break;
//                    case UT.Pth:
//                        //TODO P3 unimplemented
//                        break;
//                    case UT.Pump:
//                        //TODO  P3 unimplemented
//                        break;
//                    case UT.Watchdog:
//                        //TODO P3 unimplemented
//                        break;
//                    case UT.EngLogger:
//                        writeLine("Running Engineering Logger Unit Test\n\r");
//                        //TestManager.RunTest(typeof(UnitTestEngLogger));
//                        break;
//                    case UT.Iridium:
//                        writeLine("Running Iridium Unit Test\n\r");
//                        //TestManager.RunTest(typeof(UnitTestIridium));
//                        break;
//                    case UT.Rudics:
//                        writeLine("Running Rudics Unit Test\n\r");
//                        //TestManager.RunTest(typeof(UnitTestIridiumRUDICS));
//                        break;
//                    case UT.EMonBatt:
//                        writeLine("Running Pump Energy Monitor Test\n\r");
//                        //TestManager.RunTest(typeof(UnitTest_MotherBoard_EnergyMonitor),"TestEnergyMonitorVI");
//                        break;
//                    case UT.EMonPump:
//                        writeLine("Running Pump Energy Monitor Pump\n\r");
//                        //TestManager.RunTest(typeof(UnitTest_MotherBoard_EnergyMonitor),"TestEnergyMonitorPump");
//                        break;
//                    case UT.Msc:
//                        writeLine("Running MSC Unit Test\n\r");
//                        //TestManager.RunTest(typeof(UnitTestMsc),"TestSample");
//                        break;
//                    default:
//                        writeLine("Unknown Unit Test \r\n");
//                        break;
//                }
//            }

//        }

//        private UT DecodeUnitTest(string s)
//        {
//            s = s.ToLower();
//            if (string.Equals(s, "console"))
//                return UT.Console;
//            if (string.Equals(s, "zmodem"))
//                return UT.ZmodemConsole;
//            if (string.Equals(s, "englogger"))
//                return UT.EngLogger;
//            if (string.Equals(s, "iridium"))
//                return UT.Iridium;
//            if (string.Equals(s, "rudics"))
//                return UT.Rudics;
//            if (string.Equals(s, "ctd"))
//                return UT.Ctd;
//            if (string.Equals(s, "optode"))
//                return UT.Optode;
//            if (string.Equals(s, "pump"))
//                return UT.Pump;
//            if (string.Equals(s, "pth"))
//                return UT.Pth;
//            if (string.Equals(s, "gps"))
//                return UT.Gps;
//            if (string.Equals(s, "elmo"))
//                return UT.Elmo;
//            if (string.Equals(s, "energymonbatt"))
//                return UT.EMonBatt;
//            if (string.Equals(s, "energymonpump"))
//                return UT.EMonPump;
//            if (string.Equals(s, "watchdog"))
//                return UT.Watchdog;
//            if (string.Equals(s, "msc"))
//                return UT.Msc;
//            return UT.Unknown;
//        }

//        private void cpormv(CMD type)
//        {
//            int sarg = 0;
//            bool overwrite = false;
//            //ok this has to have multiple inputs
//            if (cmdtok.Length < 3)
//            {
//                writeLine("usage: cp <src> <dest>\r\n");
//                return;
//            }

//            //create offset if flag exists
//            sarg = (cmdtok[1][0] == '-') ? 1 : 0;
//            overwrite = (sarg == 1) ? true : false;

//            // Change and verify inputs.
//            changeWorkingDir(ref srcdir, 1 + sarg);
//            try
//            {
//                if (File.Exists(srcdir.ToString()) == false)
//                {
//                    writeLine("ERROR: No such source file.\r\n");
//                    return;
//                }
//            }
//            catch
//            {
//                writeLine("ERROR: No such source file.\r\n");
//                return;
//            }

//            changeWorkingDir(ref desdir, 2 + sarg);
//            if (Path.GetDirectoryName(desdir.ToString()) == String.Empty ||
//                Path.GetDirectoryName(desdir.ToString()) == null)
//            {
//                writeLine("ERROR: No such destination directory.\r\n");
//                return;
//            }

//            try
//            {
//                if (File.Exists(desdir.ToString()) == true && overwrite == false)
//                {
//                    writeLine(Path.GetFileName(desdir.ToString()) + ":exists, use -f flag to overwrite\r\n");
//                    return;
//                }
//            }
//            catch
//            {
//                writeLine("ERROR: No such destination directory.\r\n");
//                return;
//            }

//            //OK We can attempt the copy.
//            try
//            {
//                if (type == CMD.CP)
//                    File.Copy(srcdir.ToString(), desdir.ToString(), overwrite);
//                else if (type == CMD.MV)
//                    File.Move(srcdir.ToString(), desdir.ToString());

//            }
//            catch
//            {
//                if (type == CMD.CP) writeLine("ERROR: Copy Failed\r\n");
//                else if (type == CMD.MV) writeLine("ERROR: Move Failed\r\n");
//                return;
//            }

//            if (type == CMD.CP) writeLine("1 File(s) copied.\r\n");
//            else if (type == CMD.MV) writeLine("1 File(s) moved.\r\n");


//        }

//        private void cd()
//        {
//            changeWorkingDir(ref srcdir, 1);
//            try
//            {
//                if (Directory.Exists(srcdir.ToString()) == false)
//                {
//                    writeLine("ERROR: No such directory.\r\n");
//                    return;
//                }
//            }
//            catch
//            {
//                writeLine("ERROR: No such directory.\r\n");
//                return;
//            }

//            pwDir.Clear();
//            pwDir.Append(srcdir);
//            writeLine("Changed working directory to " + pwDir.ToString());
//        }

//        private void dir()
//        {
//            changeWorkingDir(ref srcdir, 1);

//            try
//            {
//                if (Directory.Exists(srcdir.ToString()) == false)
//                {
//                    writeLine("ERROR: No such directory.\r\n");
//                    return;
//                }
//            }
//            catch
//            {
//                writeLine("ERROR: Invalid Input\r\n");
//                return;
//            }

//            Path path;
//            //list files in directory
//            //Array.Clear(dirbuff, 0, dirbuff.Length);
//            string[] dirbuff = Directory.GetFiles(srcdir.ToString());
            
//            writeLine("\r\nFiles in " + srcdir.ToString() + "\r\n");
//            for (int i = 0; i < dirbuff.Length; i++)
//                writeLine("\t" + Path.GetFileName(dirbuff[i]) + "\r\n");

//            //list directories in directory
//            //Array.Clear(dirbuff, 0, dirbuff.Length);
//            dirbuff = Directory.GetDirectories(srcdir.ToString());
//            writeLine("\r\nDirectories in " + srcdir.ToString() + "\r\n");
//            for (int i = 0; i < dirbuff.Length; i++)
//            {
//                writeLine("\t" + dirbuff[i] + "\r\n");
//            }


//        }

//        private void changeWorkingDir(ref StringBuilder sb, int offset)
//        {
//            sb.Clear();

//            //Form the directory input
//            if (cmdtok.Length == 1)
//            {
//                sb.Append(pwDir);
//            }
//            else
//            {
//                if (cmdtok[offset][0] == '\\') //This a is fully qualified path.
//                    sb.Append(cmdtok[offset]);
//                else
//                {
//                    sb.Append(pwDir);
//                    sb.Append("\\");
//                    sb.Append(cmdtok[offset]);
//                }
//            }
//        }

//        private void presentWorkingDirectory()
//        {
//            writeLine(this.pwDir.ToString() + "\r\n");
//        }

//        private void printHelp()
//        {
//            writeLine("AVAILABLE COMMANDS:\r\n");
//            writeLine("HELP  - This printout\r\n");
//            writeLine("PWD   - Present Working Dir\r\n");
//            writeLine("DIR   - List files in PWD\r\n");
//            writeLine("CD    - Change Directory\r\n");
//            writeLine("MKDIR - Make Directory\r\n");
//            writeLine("CP    - Copy\r\n");
//            writeLine("RM    - Delete/Remove\r\n");
//            writeLine("MV    - Move\r\n");
//            writeLine("SZ    - Send via ZMODEM\r\n");
//            writeLine("RZ    - Receive via ZMODEM\r\n" +
//                      "UT    - Conduct Unit Test\r\n" +
//                      "REBOOT- Hard Reboot Processor\r\n" +
//                      "COM   - Open an native or i2c serial port\r\n" +
//                      "        (enable power first)\r\n" +
//                      "POW   - Switch power on available channels.\r\n");
//        }

//        private CMD decodeCommand(string s)
//        {
//            s = s.ToLower();
//            if (String.Equals(s, "help"))
//                return CMD.HELP;
//            if (String.Equals(s, "pwd"))
//                return CMD.PWD;
//            if (String.Equals(s, "dir"))
//                return CMD.DIR;
//            if (String.Equals(s, "cd"))
//                return CMD.CD;
//            if (String.Equals(s, "mkdir"))
//                return CMD.MKDIR;
//            if (String.Equals(s, "cp"))
//                return CMD.CP;
//            if (String.Equals(s, "rm"))
//                return CMD.RM;
//            if (String.Equals(s, "mv"))
//                return CMD.MV;
//            if (String.Equals(s, "sz"))
//                return CMD.SZ;
//            if (String.Equals(s, "rz"))
//                return CMD.RZ;
//            if (String.Equals(s, "ut"))
//                return CMD.UT;
//            if (String.Equals(s, "com"))
//                return CMD.COM;
//            if (String.Equals(s, "pow"))
//                return CMD.POW;
//            if (String.Equals(s, "reboot"))
//                return CMD.REBOOT;
//            if (String.Equals(s, "date"))
//                return CMD.DATE;
//            if (String.Equals(s, "set"))
//                return CMD.SET;
//            if (String.Equals(s, "cpf"))
//                return CMD.CPF;
//            return CMD.UNKNOWN;

//        }

//        public void SendLine(StringBuilder builder)
//        {
//            writeLine(builder.ToString());
//        }
    }
}
