using System;
using Microsoft.SPOT;

using System.Text;
using System.IO;

using Microsoft.SPOT.IO;

using GHI.IO.Storage;

using MissionClass;

namespace CPF
{
    public class Mission
    {
        public static PressureTable[] descendTable;
        public static PressureTable[] ascendTable;

        public static TimeSpan parkSamplePeriod;
        public static bool recoveryMode = true;
        public static int maxProfiles = 10;
        
		private static StringBuilder fileName = new StringBuilder(128);
        private static FileStream missionFile;

        public static StringBuilder missionFileName = new StringBuilder(128);
        private static StringBuilder sbTemp = new StringBuilder(256);

        private static FullMission mission60mHoldAt6 = new FullMission();

        public enum Missions : int
        {
            mission60mHold8 = 0,
            missionHoldAt5m,
            mission60mNoHold,
            mission150mNoHold,
            mission150m40mHold
        }

        public static void createMission(Missions missionNum)
        {
            float pressure = (float)0.0;

            switch (missionNum)
            {
                case (Missions.mission60mHold8):
                    descendTable = new PressureTable[1];
                    ascendTable = new PressureTable[19];

                    recoveryMode = true;
                    parkSamplePeriod = new TimeSpan(0, 1, 0);

                    //First the descend table
                    descendTable[0].pressure = (float)60.0;   //decibar
                    descendTable[0].PV = (float)-0.10;      //decibar per second
                    descendTable[0].parkTime = new TimeSpan(0, 5, 0);
                    descendTable[0].sampleList = (byte)7;

                    pressure = (float)60.0;

                    //Now the ascend table
                    for (int i = 0; i < ascendTable.Length; i++)
                    {
                        if (pressure > 20)
                        {
                            ascendTable[i].pressure = pressure;
                            ascendTable[i].parkTime = new TimeSpan(0, 0, 0);
                            pressure = pressure - (float)5.0;
                        }
                        else
                        {
                            ascendTable[i].pressure = pressure;

                            if (pressure == 8.0)
                                ascendTable[i].parkTime = new TimeSpan(0, 1, 0);
                            else
                                ascendTable[i].parkTime = new TimeSpan(0, 0, 0);

                            pressure = pressure - (float)2.0;
                        }

                        ascendTable[i].PV = (float)0.10;
                        ascendTable[i].sampleList = (byte)7;
                    }
                    break;
                case (Missions.missionHoldAt5m):
                    descendTable = new PressureTable[1];
                    ascendTable = new PressureTable[3];

                    recoveryMode = false;
                    parkSamplePeriod = new TimeSpan(0, 1, 0);

                    //First the descend table
                    descendTable[0].pressure = (float)60.0;   //decibar
                    descendTable[0].PV = (float)-0.05;      //decibar per second
                    descendTable[0].parkTime = new TimeSpan(0, 3, 0);
                    descendTable[0].sampleList = (byte)7;

                    pressure = (float)60.0;

                    //Now the ascend table
                    ascendTable[0].pressure = (float)5.0;   //decibar
                    ascendTable[0].PV = (float)0.05;      //decibar per second
                    ascendTable[0].parkTime = new TimeSpan(0, 3, 0);
                    ascendTable[0].sampleList = (byte)7;
                    
                    ascendTable[1].pressure = (float)3.0;   //decibar
                    ascendTable[1].PV = (float)0.05;      //decibar per second
                    ascendTable[1].parkTime = new TimeSpan(0, 0, 0);
                    ascendTable[1].sampleList = (byte)7;

                    ascendTable[2].pressure = (float)0.0;   //decibar
                    ascendTable[2].PV = (float)0.05;      //decibar per second
                    ascendTable[2].parkTime = new TimeSpan(0, 0, 0);
                    ascendTable[2].sampleList = (byte)7;

                    break;
                case (Missions.mission60mNoHold):
                    descendTable = new PressureTable[1];
                    ascendTable = new PressureTable[19];

                    recoveryMode = true;
                    parkSamplePeriod = new TimeSpan(0, 1, 0);

                    //First the descend table
                    descendTable[0].pressure = (float)60.0;   //decibar
                    descendTable[0].PV = (float)-0.10;      //decibar per second
                    descendTable[0].parkTime = new TimeSpan(0, 2, 0);
                    descendTable[0].sampleList = (byte)7;

                    pressure = (float)60.0;

                    //Now the ascend table
                    for (int i = 0; i < ascendTable.Length; i++)
                    {
                        if (pressure > 20)
                        {
                            ascendTable[i].pressure = pressure;
                            pressure = pressure - (float)5.0;
                        }
                        else
                        {
                            ascendTable[i].pressure = pressure;
                            pressure = pressure - (float)2.0;
                        }
                        ascendTable[i].PV = (float)0.10;
                        ascendTable[i].sampleList = (byte)7;
                        ascendTable[i].parkTime = new TimeSpan(0, 0, 0);
                    }
                    break;

                case (Missions.mission150mNoHold):
                    descendTable = new PressureTable[1];
                    ascendTable = new PressureTable[37];

                    recoveryMode = true;     
                    parkSamplePeriod = new TimeSpan(0, 1, 0);

                    //First the descend table
                    descendTable[0].pressure = (float)150.0;   //decibar
                    descendTable[0].PV = (float)-0.20;      //decibar per second
                    descendTable[0].parkTime = new TimeSpan(0, 5, 0);
                    descendTable[0].sampleList = (byte)7;

                    pressure = (float)150.0;

                    //Now the ascend table
                    for (int i = 0; i < ascendTable.Length; i++)
                    {
                        if (pressure > 20)
                        {
                            ascendTable[i].pressure = pressure;
                            pressure = pressure - (float)5.0;
                        }
                        else
                        {
                            ascendTable[i].pressure = pressure;
                            pressure = pressure - (float)2.0;
                        }
                        ascendTable[i].PV = (float)0.10;
                        ascendTable[i].sampleList = (byte)7;
                        ascendTable[i].parkTime = new TimeSpan(0, 0, 0);
                    }
                    break;

                case (Missions.mission150m40mHold):
                    descendTable = new PressureTable[1];
                    ascendTable = new PressureTable[37];

                    recoveryMode = true;       //GM Changed 2015Aug11
                    parkSamplePeriod = new TimeSpan(0, 1, 0);

                    //First the descend table
                    descendTable[0].pressure = (float)150.0;   //decibar
                    descendTable[0].PV = (float)-0.10;      //decibar per second
                    descendTable[0].parkTime = new TimeSpan(0, 15, 0);
                    descendTable[0].sampleList = (byte)7;

                    pressure = (float)150.0;

                    //Now the ascend table
                    for (int i = 0; i < ascendTable.Length; i++)
                    {
                        if (pressure > 20)
                        {
                            ascendTable[i].pressure = pressure;
                            
                            if (pressure == 40.0)
                                ascendTable[i].parkTime = new TimeSpan(0, 10, 0);
                            else
                                ascendTable[i].parkTime = new TimeSpan(0, 0, 0);
 
                            pressure = pressure - (float)5.0;
                        
                        }
                        else
                        {
                            ascendTable[i].pressure = pressure;
                            ascendTable[i].parkTime = new TimeSpan(0, 0, 0);
                            pressure = pressure - (float)2.0;
                        }
                        ascendTable[i].PV = (float)0.10;
                        ascendTable[i].sampleList = (byte)7;
                    }
                    break;
            }

            //Last entry in the ascend table must have a park time of zero
            if (ascendTable[ascendTable.Length - 1].parkTime != TimeSpan.Zero)
            {
                EngrLogger.writeToColumns("Forcing last park time entry in ascend table to zero");
                ascendTable[ascendTable.Length - 1].parkTime = TimeSpan.Zero;
            }
        }

        public static void BTSendMission()
        {

            sbTemp.Clear();
            sbTemp.Append("Recovery mode = ");
            sbTemp.Append(recoveryMode.ToString());
            EngrLogger.writeToColumns(sbTemp);

            sbTemp.Clear();
            sbTemp.Append("Park Sample Period = ");
            sbTemp.Append(parkSamplePeriod.ToString());
            EngrLogger.writeToColumns(sbTemp);

            for (int i = 0; i < descendTable.Length; i++)
            {
                sbTemp.Clear();
                sbTemp.Append("Descend table ");
                sbTemp.Append(i.ToString());
                sbTemp.Append(" Pressure, PV, Park Time, sample list: ");
                sbTemp.Append(descendTable[i].pressure.ToString());
                sbTemp.Append(", ");
                sbTemp.Append(descendTable[i].PV.ToString("f3"));
                sbTemp.Append(", ");
                sbTemp.Append(descendTable[i].parkTime.ToString());
                sbTemp.Append(", ");
                sbTemp.Append(descendTable[i].sampleList.ToString());
                EngrLogger.writeToColumns(sbTemp);
            }

            for (int i = 0; i < ascendTable.Length; i++)
            {
                sbTemp.Clear();
                sbTemp.Append("Ascend table ");
                sbTemp.Append(i.ToString());
                sbTemp.Append(" Pressure, PV, Park Time, sample list: ");
                sbTemp.Append(ascendTable[i].pressure.ToString());
                sbTemp.Append(", ");
                sbTemp.Append(ascendTable[i].PV.ToString("f3"));
                sbTemp.Append(", ");
                sbTemp.Append(ascendTable[i].parkTime.ToString());
                sbTemp.Append(", ");
                sbTemp.Append(ascendTable[i].sampleList.ToString());
                EngrLogger.writeToColumns(sbTemp);
            }
        }

        public static void loadMissionFromSD()
        {
            fileName.Clear();
            fileName.Append(EngrLogger.sdVol.RootDirectory);
            fileName.Append(@"\");
            fileName.Append(Program.missionFileName);

            missionFile = new FileStream(fileName.ToString(), FileMode.Open, FileAccess.Read);
            int fileLength = (int)missionFile.Length;
            byte[] fileBuffer = new byte[fileLength];
            missionFile.Read(fileBuffer, 0, fileLength);
            FullMission missionFromFile = (FullMission)Reflection.Deserialize(fileBuffer, typeof(FullMission));

            missionFile.Close();

            //Set mission recoverMode
            recoveryMode = missionFromFile.recoveryMode;

            //Set mission sampleTime
            parkSamplePeriod = new TimeSpan(0, missionFromFile.samplePeriod.Minutes,
                                                missionFromFile.samplePeriod.Seconds);

            //Fill descend table
            descendTable = new PressureTable[(int)missionFromFile.descendTable.Length];
            for (int i = 0; i < missionFromFile.descendTable.Length; i++)
            {
                descendTable[i].pressure = missionFromFile.descendTable[i].pressure;
                descendTable[i].PV = missionFromFile.descendTable[i].PV;
                descendTable[i].parkTime = new TimeSpan(missionFromFile.descendTable[i].parkTime.Hours,
                                                        missionFromFile.descendTable[i].parkTime.Minutes,
                                                        missionFromFile.descendTable[i].parkTime.Seconds);
                descendTable[i].sampleList = missionFromFile.descendTable[i].sampleList;
            }

            //Fill ascend table
            ascendTable = new PressureTable[(int)missionFromFile.ascendTable.Length];
            for (int i = 0; i < missionFromFile.ascendTable.Length; i++)
            {
                ascendTable[i].pressure = missionFromFile.ascendTable[i].pressure;
                ascendTable[i].PV = missionFromFile.ascendTable[i].PV;
                ascendTable[i].parkTime = new TimeSpan(missionFromFile.ascendTable[i].parkTime.Hours,
                                                        missionFromFile.ascendTable[i].parkTime.Minutes,
                                                        missionFromFile.ascendTable[i].parkTime.Seconds);
                ascendTable[i].sampleList = missionFromFile.ascendTable[i].sampleList;
            }
        }
    }
}
