using System;
using HWModules;
using SWModules;

using System.Text;
using System.Threading;
using Microsoft.SPOT;
using SensorModules;

namespace CPF.Profile_States
{
    public class Ascend : Profile
    {
        public Ascend(string name)
        {
            stateName.Clear();
            stateName.Append(name);

            ECTimeout = 30 * 60 * 1000;
        }

        public enum Action : int
        {
            ascendActions = 1,
            lastAction,
            size = lastAction
        }
        private static Action currentAction;

        public int CurrentAction
        {
            get { return (int)currentAction; }
        }

        public override int doStateEntryActions()
        {
            basicStateEntry();

            ProfileState.Clear();
            ProfileState.Append(profileStateNone);

            sbTemp.Clear();
            sbTemp.Append(DateTime.Now.ToString("yyyy-MMM-ddTHH:mm:ssZ"));
            sbTemp.Append(Literals.tabChar);
            sbTemp.Append("Start Ascend, bellows position = ");
            sbTemp.Append(SV.BellowsPosition.ToString("f2"));
            SciLogger.writeToLog(sbTemp);

            sbTemp.Clear();
            sbTemp.Append("Start Ascend");
            sbTemp.Append(Literals.tabChar);
            sbTemp.Append(DateTime.Now.ToString("yyyy-MMM-ddTHH:mm:ssZ"));
            SciLogger.appendToMsgFooter(sbTemp);

            skipDeepStations();

            currentAction = (Action)1;

            msc1.ResetSequencers();

            buoyancyEngine.openMV();
            Thread.Sleep(500);

            SV.RunPVPID = true;
            MessageQueue mq = MessageQueue.Instance;
            mq.processQMaxLimit();

            SBE41CTD.runAscendPVPID = true;

            return (1);
        }

        public override int doStateActions()
        {

            switch (currentAction)
            {
                #region Sequential state actions
                case (Action.ascendActions):
                    nextAction = setPV();
                    SV.RunPVPID = true;

                    msc1.SequenceT1T2Samples();

                    break;
                case (Action.lastAction):
                    //here for consistancy, but will likely never get here as setPV returns (int)1.
                    currentAction = Action.ascendActions;
                    break;
                #endregion
            }

            currentAction = (Action)checkActionReturn(nextAction, (int)currentAction);

            return (1);
        }

        private const bool inAscend = false;

        public override CPFStates checkEvents()
        {
            // If we aren't at the last entry in the ascend table and it isn't a park station
            // check if CPF passed a target Pressure and if so increment PressureTableNum
            // if it is a park station, transition to park state
            if ((SV.PressureTableNum < Mission.ascendTable.Length) && (ctd1.SBE41LPF.RawPressure <= PressureSetPoint))
            {
                if (getParkTime() == TimeSpan.Zero)
                {
                    SciLogger.startNewSampleCycle(SciLogger.Instruments.AllInstruments);
                    SV.PressureTableNum++;
                }
                else
                {
                    PVSetPoint = 0.0;
                    return (CPFStates.park);
                }
            }

            //check if float is at surface
            if (ctd1.SBE41LPF.RawPressure < (MissionConfig.CpPressureCutoff + 0.5))
            {
                // is CTD in CP mode, and will data need to be dumped?
                if (MissionConfig.CPMode)
                {
                    ctd1.sendStopProfile();
                }

                sbTemp.Clear();
                sbTemp.Append("At CP mode pressure cutoff, stopping profile: ");
                sbTemp.Append(DateTime.Now.ToString("dd-MMM-yyyy HH:mm:ss"));
                SciLogger.appendToMsgHeader(sbTemp);
                EngrLogger.Comment(sbTemp.ToString());

                // We need check if the last ascension point is complete

                return (CPFStates.surfaceOpsSetBellows);
            }
            return (CPFStates.ascend);
        }

        public override int doExitActions(bool timedOut)
        {
            ctd1.sendStopProfile();
            msc1.ResetSequencers();
            gps1.powerUp();
            btConsole.powerUp();

            if (timedOut)
            {
                sbTemp.Clear();
                sbTemp.Append("Ascend State Timed Out: ");
                sbTemp.Append(DateTime.Now.ToString("dd-MMM-yyyy HH:mm:ss"));
                SciLogger.appendToMsgHeader(sbTemp);
                EngrLogger.Comment(sbTemp.ToString());

                basicStateExit(true);
            }
            else
            {
                sbTemp.Clear();
                sbTemp.Append("Ascend State Normal Exit: ");
                sbTemp.Append(DateTime.Now.ToString("dd-MMM-yyyy HH:mm:ss"));
                SciLogger.appendToMsgHeader(sbTemp);
                EngrLogger.Comment(sbTemp.ToString());

                basicStateExit(false);
            }

            //SciLogger.endSampleCycle();

            return (1);
        }

        public override CPFStates doTimeoutAction()
        {
            return (CPFStates.initProfile);
        }

        private int skipDeepStations()
        {
            for (int i = 0; i < Mission.ascendTable.Length; i++)
            {
                if (ctd1.SBE41LPF.RawPressure < Mission.ascendTable[SV.PressureTableNum].pressure)
                    SV.PressureTableNum = SV.PressureTableNum + 1;
            }

            sbTemp.Clear();
            sbTemp.Append("Starting at ascend table depth = ");
            sbTemp.Append(Mission.ascendTable[SV.PressureTableNum].pressure.ToString());
            EngrLogger.writeToColumns(sbTemp);

            return (1);
        }
    }
}
