using System;
using HWModules;
using SWModules;

using System.Threading;
using SensorModules;

namespace CPF.Surface_States
{

    public class ABDecreaseBuoyancyFast : StateBase
    {
        public ABDecreaseBuoyancyFast(string name)
        {
            stateName.Clear();
            stateName.Append(name);

            ECTimeout = 15 * 60 * 1000;      //60 minutes
        }

        private enum Action : int
        {
            disablePower = 1,
            setBellows,
            lastAction,
            size = lastAction
        }
        private static Action currentAction;

        private TimeSpan stateEntryTime;

        public override int doStateEntryActions()
        {
            basicStateEntry();
            ABRetractThresholdCount = 0;

            sbTemp.Clear();
            sbTemp.Append("Decreasing Buoyancy to pressure = ");
            sbTemp.Append(MissionConfig.ABPressureThreshold.ToString("f2"));
            sbTemp.Append(" at ");
            sbTemp.Append(MissionConfig.ABRetractFastJV.ToString());
            sbTemp.Append(" cps");
            EngrLogger.writeToColumns(sbTemp);

            ctd1.LPFPressure(ctd1.SBE41LPF.RawPressure, DateTime.Now.Ticks / 10000000.0, MissionConfig.SBE41CommandModeSamplePeriod, true);
            buoyancyEngine.resetPVPID();

            ctd1.clearRawPresureDL();

            stateEntryTime = Microsoft.SPOT.Hardware.Utility.GetMachineTime();

            currentAction = (Action)1;
  
            return (1);
        }

        public override int doStateActions()
        {

            switch (currentAction)
            {
                case (Action.disablePower):
                    //TODO P1 disable/enablePower should be methods like Dis/EnableCoreSensors, Dis/EnableScienceSensors, ...
                    EngrLogger.Comment("Checking global issues before power down");
                    checkGlobalIssues();
                    EngrLogger.writeToColumns("Disabling unneeded power");
                    msc1.powerDown();
                    gps1.powerDown();
                    msc1.powerDown();
                    flbb1.powerDown();
                    optode1.powerDown();
                    radiometer1.powerDown();

                    EngrLogger.writeToColumns("Powering down Bluetooth");
                    Thread.Sleep(3000);
                    //btConsole.powerDown();   TODO P0 this is only commented out ffor testing dual lead controller 

                    ABRetractThresholdCount = 0;
    
                    nextAction = (int)Action.setBellows;

                    EngrLogger.Comment("Checking global issues after power down");
                    checkGlobalIssues();
                    break;
                case (Action.setBellows):
                    if (!buoyancyEngine.decreasingBuoyancy)
                        buoyancyEngine.decreaseBuoyancy(MissionConfig.ABRetractFastJV);

                    nextAction = (int)Action.setBellows;
                    break;
                case (Action.lastAction):
                    //do nothing here
                    break;

                default:
                    break;
            }

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

            return (1);
        }

        public override CPFStates checkEvents()
        {
//            if (checkForJustNegative())
            if (currentAction == Action.setBellows)
            {
                if (ctd1.checkForJustNegative())
                {
                    buoyancyEngine.stopMotor();

                    sbTemp.Clear();
                    sbTemp.Append(DateTime.Now.ToString("yyyy-MMM-ddTHH:mm:ssZ"));
                    sbTemp.Append(Literals.tabChar);
                    sbTemp.Append("Exiting Dec Buocy depth > threshold ");
                    sbTemp.Append(MissionConfig.ABPressureThreshold.ToString("f1"));
                    sbTemp.Append(" dBar");
                    sbTemp.Append(Literals.tabChar);
                    sbTemp.Append(ctd1.SBE41LPF.RawPressure.ToString("f2"));
                    sbTemp.Append(Literals.tabChar);
                    sbTemp.Append(SV.BellowsPosition.ToString("f2"));
                    sbTemp.Append(Literals.tabChar);
                    sbTemp.Append(SV.busVoltage.ToString("f2"));
                    sbTemp.Append(Literals.tabChar);
                    sbTemp.Append(SV.busAmps.ToString("f2"));
                    SciLogger.writeToLog(sbTemp);
                    SciLogger.appendToMsgFooter(sbTemp);
                    EngrLogger.writeToColumns(sbTemp.Replace(Literals.tabChar, Literals.commaChar));

                    return (CPFStates.descend);
                }
                else return (CPFStates.ABDecBuocyFast);
            }
            else
            {
                return (CPFStates.ABDecBuocyFast);
            }
        }

        public override int doExitActions(bool timedOut)
        {
            if (timedOut)
            {
                basicStateExit(true);
            }
            else
            {
                basicStateExit(false);
            };

            return (1);
        }

        public override CPFStates doTimeoutAction()
        {
            //TODO P1 This probably isn't right, we're trying to get rid of ABDecBuocySlow
            return (CPFStates.ABDecBuocySlow);
        }

        private static double lastRawPressure = 0.0;

        private bool checkForJustNegative()
        {

            if ((ctd1.SBE41LPF.RawPressure > -1.0) && (ctd1.SBE41LPF.RawPressure < 2.0))
            {
                if (ctd1.SBE41LPF.RawPressure >= MissionConfig.ABPressureThreshold)
                    ABRetractThresholdCount = ABRetractThresholdCount + 1;
                else
                    ABRetractThresholdCount = 0;
                lastRawPressure = ctd1.SBE41LPF.RawPressure;
            }
            else
            {
                sbTemp.Clear();
                sbTemp.Append("Throwing away bad pressure in checkForJustNegative: ");
                sbTemp.Append(ctd1.SBE41LPF.RawPressure.ToString());
                EngrLogger.writeToColumns(sbTemp);
            }

            if (currentAction == Action.setBellows)
            {
                if (ABRetractThresholdCount >= 3)
                    return (true);
                else
                    return (false);
            }
            else
                return (false);
        }

    }
}
