using System;

using System.Text;

namespace SWModules
{
    public class Utils
    {
        public static int getField(byte[] inBytes, byte token, int desiredField, ref byte[] returnField)
        {
            int currentField = 0;
            int returnFieldIndex = 0;
            bool inDesiredField;

            //TODO P2 I don't think we need this block and it doesn't look like returnFieldIndex means anything
            if (desiredField == 0)
                inDesiredField = true;
            else
                inDesiredField = false;

            Array.Clear(returnField, 0, returnField.Length);

            for (int i = 0; i < inBytes.Length; i++)
            {
                if ((inBytes[i] == token) && !inDesiredField)
                    currentField++;
                else if (currentField == desiredField)
                {
                    inDesiredField = true;
                    if ((inBytes[i] == token) || (inBytes[i] == 10) || (inBytes[i] == 13))
                        return (returnFieldIndex);
                    returnField[returnFieldIndex++] = inBytes[i];
                    if (returnFieldIndex >= returnField.Length)
                        return returnFieldIndex;
                }
            }
            return (0);
        }

        public static int getField(StringBuilder inSB, char token, int desiredField, ref StringBuilder returnField)
        {
            int currentField = 0;
            int returnFieldIndex = 0;
            bool inDesiredField;

            //TODO P2 I don't think we need this block and it doesn't look like returnFieldIndex means anything
            if (desiredField == 0)
                inDesiredField = true;
            else
                inDesiredField = false;

            returnField.Clear();
            
            for (int i = 0; i < inSB.Length; i++)
            {
                if ((inSB[i] == token) && !inDesiredField)
                    currentField++;
                else if (currentField == desiredField)
                {
                    inDesiredField = true;
                    if ((inSB[i] == token) || (inSB[i] == 10) || (inSB[i] == 13))
                        return (returnFieldIndex);
                    returnField.Append(inSB[i]);
                    if (returnFieldIndex >= returnField.Length)
                        return returnFieldIndex;
                }
            }
            return (0);
        }

        /// <summary>
        /// Compares values in sequence for two byte arrays, and returns true if A = B for the subset that is identified.
        /// </summary>
        /// <param name="aBytes">Input Array to check</param>
        /// <param name="aOffset">Array offset to start comparison in A</param>
        /// <param name="bBytes">Second input array to check</param>
        /// <param name="bOffset">Array offset for second input</param>
        /// <param name="count">Number of bytes to compare</param>
        /// <returns></returns>
        public static bool CompareArray(byte[] aBytes, int aOffset, byte[] bBytes, int bOffset, int count)
        {
            if ((aBytes.Length < aOffset+count)||(bBytes.Length < bOffset+count))
                return false;
            for (int i = 0; i < count; i++)
            {
                if (aBytes[i + aOffset] != bBytes[bOffset + i])
                    return false;
            }

            return true;

        }

        public static uint SecondsSinceEpoch
        {
            get
            {
                TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1);
                return (uint)(t.Seconds + t.Minutes * 60 + t.Hours * 3600 + t.Days * 86400);
            }
        }

        public static uint dateTimeToPosixTime(DateTime timeNow)
        {
            TimeSpan t = timeNow - new DateTime(1970, 1, 1);
            return (uint)(t.Seconds + t.Minutes * 60 + t.Hours * 3600 + t.Days * 86400);
        }


    }

  
    public enum WfrState
      {
            Waiting = 0,
            GotResponse = 1,
            NotWaiting = -2,
            TimedOut = -1,
    }
}

//From the old todo.cs file
//TODO P1 See if the logic to dumpCPData is right, might need to rework booleans so there is a flag that goes true if we actually get into CP mode
//TODO P1 check if float is at surface for example:
//if (ctd.SBE41LPF.Pressure< (configFile.cpPressureCutoff + 0.5))
//{
//    //is CTD in CP mode, and will data need to be dumped?
//    if (configFile.CPMode)
//    {
//        DumpCPData = true;
//        return (Program.CPFStates.initProfile);
//    }
//    return (Program.CPFStates.initProfile);
//TODO P2 Implement watchdog functionality
//TODO P2  Add qS.ErrorCode everywhere and handle like SBE41.
//TODO P2  All commands sent to devices should log themselves
//TODO P2 Add messageIndex check in all IO drivers to make sure we don't spin off the end of the messageBytes array.  Link it to Queue width
//TODO P2  Add error checking to Elmo read and writes
//TODO P2  Add Elmo monitor functions
//TODO P2 Deal with failure in initMission actions like checkValveAction
//TODO P2 Be sure to test pressure tables with multiple park stations
//TODO P2 Reduce verbosity level in recovery mode
//TODO P2 Make verbosity level functional
//TODO P2 Make sure all .Parse methods work on char array not byte array with 0 elements after the value
//TODO P2 Should setPV set SV.RunPID true?
//TODO P2 Investigate why 1 Hz CTD data is noiser than .3 Hz data
//TODO P2 Deal with extend/retract bellows return(false) condition
//TODO P2 make sure ascend will find the surface even if SBE41 doesn't e.g. look for GPS signal above 10 meters or something like that
//TODO P2 Make SV.checkStruckPressure = true in basicStateEntry and make false where needed
//TODO P2 Deal with all checkForResponse return codes instead of assuming everything worked
//TODO P2 Probably should re-work descend and ascend so it doesn't call setPV if it isn't a park station
//TODO P2 Use checkBellowsPosition outside limits as test case for how to structure error repsonse.  Example, detecting an outside limits condition should prevent any further motion in that directin by any method or state
//TODO P2 Change create standard mission to allows park time to be passed in as a parameter
//TODO P2  Deal with the issue in the 4th line down
//$	10-Nov-2015	10:23:54.280	Dump CP Data	Unparsed SBE41 Message					    8.90, 19.6494, 34.7218  																														
//$	10-Nov-2015	11:48:38.953	Dump CP Data	RecMode false, PID Off, Stopped, Scend sub: Outside Band, depthNum = 0	2.170000	63.304885	29.875000																										0.185000	-100.000000					
//$	10-Nov-2015	11:48:41.785	Dump CP Data	Didn't get dd response, restarting command timer
//$	10-Nov-2015	11:48:41.784	Dump CP Data	Unparsed SBE41 Message					SBE41 waitingForResponse expended all retries																														
//$	10-Nov-2015	11:48:42.191	Dump CP Data	RecMode false, PID Off, Stopped, Scend sub: Outside Band, depthNum = 0	2.170000	63.305910	29.875000																										0.195000	-100.000000					
//$	10-Nov-2015	11:48:44.831	Dump CP Data	Unparsed SBE41 Message					S>  																														
//$	10-Nov-2015	10:23:57.211	Dump CP Data	Unparsed SBE41 Message					    8.89, 19.6493, 34.7219  																														
//$	10-Nov-2015	11:48:46.033	Dump CP Data	Normal state exit
//$	10-Nov-2015	11:48:46.144	Dump CP Data	RecMode false, PID Off, Stopped, Scend sub: Outside Band, depthNum = 0	2.170000	63.305910	29.875000																										0.195000	-100.000000					
//$	10-Nov-2015	11:48:47.865	Surface Ops	State Entry
//$	10-Nov-2015	11:48:48.478	Surface Ops	Closing old engr log file: \SD\2015-11-10T11-13-59




