using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;

namespace VeederRoot_ATG_Console.MessageEntity.Incoming
{
    /// <summary>
    /// i|I101
    /// </summary>
    public class QuerySystemStatusReportResponse : IncomingMessageBase
    {
        public enum Alarm_Warning_Category
        {
            AllFunctionNormal = 00,
            SystemAlarm = 01,
            TankAlarm = 02,
            LiquidSensorAlarm = 03,
            VaporSensorAlarm = 04,
            InputAlarm = 05,
            VolumetricLineLeakAlarm = 06,
            GroundwaterSensorAlarm = 07,
            TypeASensorAlarm = 08,
            TypeBSensorAlarm = 12,
            UniversalSensorAlarm = 13,
            AutoDialFaxAlarm = 14,
            MechanicalDispenserInterfaceAlarm = 18,
            ELectronicDispenserInterfaceAlarm = 19,
            ProductAlarm = 20,
            PressureLineLeakAlarm = 21,
            WirelessPlldAlarm = 26,
            ExternallyDetectedAlarm_NOT_REPORTED_BY_CONSOLE = 99,
        }

        public DateTime? CurrentDateAndTime
        {
            get
            {
                if (base.FunctionCode.Item1 == MessageFormat.Display)
                    return null;
                return DateTime.ParseExact(
                    Encoding.ASCII.GetString(base.DataFieldAndOptionalCheckSumAndETX.Take(10).ToArray()),
                    "yyMMddHHmm", CultureInfo.InvariantCulture);
            }
        }

        public List<QuerySystemStatusReportData> QuerySystemStatusReportDatas
        {
            get
            {
                //6 is the length `&&` and 4 bytes check sum
                var howMany = (base.DataFieldAndOptionalCheckSumAndETX.Skip(10).Count() - 6) % 6;
                var datas = new List<QuerySystemStatusReportData>();
                for (int i = 0; i < howMany; i++)
                {
                    datas[i] =
                        new QuerySystemStatusReportData(
                            base.DataFieldAndOptionalCheckSumAndETX.Skip(10).Skip(3 * i).Take(3).ToArray());
                }

                return datas;
            }
        }

        public class QuerySystemStatusReportData
        {
            private static List<Tuple<int[], List<Tuple<int, string>>>> alarm_Type_Number_Mapping
               = new List<Tuple<int[], List<Tuple<int, string>>>>();

            static QuerySystemStatusReportData()
            {
                var aa01 = new Tuple<int[], List<Tuple<int, string>>>(new int[] { 1 }, new List<Tuple<int, string>>());
                aa01.Item2.Add(new Tuple<int, string>(1, "Printer Out Of Paper"));
                aa01.Item2.Add(new Tuple<int, string>(2, "Printer Error"));
                aa01.Item2.Add(new Tuple<int, string>(3, "EEPROM Configuration Error"));
                aa01.Item2.Add(new Tuple<int, string>(4, "Battery Off"));
                aa01.Item2.Add(new Tuple<int, string>(5, "Too Many Tanks"));
                aa01.Item2.Add(new Tuple<int, string>(6, "System Security Warning"));
                aa01.Item2.Add(new Tuple<int, string>(7, "ROM Revision Warning"));
                aa01.Item2.Add(new Tuple<int, string>(8, "Remote Display Communications Error"));
                aa01.Item2.Add(new Tuple<int, string>(9, "Autodial Error"));
                aa01.Item2.Add(new Tuple<int, string>(10, "Software Module Warning"));
                aa01.Item2.Add(new Tuple<int, string>(11, "Tank Test Shutdown Warning"));
                aa01.Item2.Add(new Tuple<int, string>(12, "Protective Cover Alarm"));
                aa01.Item2.Add(new Tuple<int, string>(13, "BIR Shift Close Pending"));
                aa01.Item2.Add(new Tuple<int, string>(14, "BIR Daily Close Pending"));
                aa01.Item2.Add(new Tuple<int, string>(15, "PC(H8) Revision Warning"));
                aa01.Item2.Add(new Tuple<int, string>(16, "System Self Test Error"));
                aa01.Item2.Add(new Tuple<int, string>(17, "System Clock Incorrect Warning"));
                aa01.Item2.Add(new Tuple<int, string>(18, "System Device Poll Timeout"));
                alarm_Type_Number_Mapping.Add(aa01);



                var aa02 = new Tuple<int[], List<Tuple<int, string>>>(new int[] { 2 }, new List<Tuple<int, string>>());
                aa02.Item2.Add(new Tuple<int, string>(1, "Tank Setup Data Warning"));
                aa02.Item2.Add(new Tuple<int, string>(2, "Tank Leak Alarm"));
                aa02.Item2.Add(new Tuple<int, string>(3, "Tank High Water Alarm"));
                aa02.Item2.Add(new Tuple<int, string>(4, "Tank Overfill Alarm"));
                aa02.Item2.Add(new Tuple<int, string>(5, "Tank Low Product Alarm"));
                aa02.Item2.Add(new Tuple<int, string>(6, "Tank Sudden Loss Alarm"));
                aa02.Item2.Add(new Tuple<int, string>(7, "Tank High Product Alarm"));
                aa02.Item2.Add(new Tuple<int, string>(8, "Tank Invalid Fuel Level Alarm"));
                aa02.Item2.Add(new Tuple<int, string>(9, "Tank Probe Out Alarm"));
                aa02.Item2.Add(new Tuple<int, string>(10, "Tank High Water Warning"));
                aa02.Item2.Add(new Tuple<int, string>(11, "Tank Delivery Needed Warning"));
                aa02.Item2.Add(new Tuple<int, string>(12, "Tank Maximum Product Alarm"));
                aa02.Item2.Add(new Tuple<int, string>(13, "Tank Gross Leak Test Fail Alarm"));
                aa02.Item2.Add(new Tuple<int, string>(14, "Tank Periodic Leak Test Fail Alarm"));
                aa02.Item2.Add(new Tuple<int, string>(15, "Tank Annual Leak Test Fail Alarm"));
                aa02.Item2.Add(new Tuple<int, string>(16, "Tank Periodic Test Needed Warning"));
                aa02.Item2.Add(new Tuple<int, string>(17, "Tank Annual Test Needed Warning"));
                aa02.Item2.Add(new Tuple<int, string>(18, "Tank Periodic Test Needed Alarm"));
                aa02.Item2.Add(new Tuple<int, string>(19, "Tank Annual Test Needed Alarm"));
                aa02.Item2.Add(new Tuple<int, string>(20, "Tank Leak Test Active"));
                aa02.Item2.Add(new Tuple<int, string>(21, "Tank No CSLD Idle Time Warning"));
                aa02.Item2.Add(new Tuple<int, string>(22, "Tank Siphon Break Active Warning"));
                aa02.Item2.Add(new Tuple<int, string>(23, "Tank CSLD Rate Increase Warning"));
                aa02.Item2.Add(new Tuple<int, string>(24, "Tank AccuChart Calibration Warning"));
                aa02.Item2.Add(new Tuple<int, string>(25, "Tank HRM Reconciliation Warning"));
                aa02.Item2.Add(new Tuple<int, string>(26, "Tank HRM Reconciliation Alarm"));
                aa02.Item2.Add(new Tuple<int, string>(27, "Tank Clod Temperature Warning"));
                aa02.Item2.Add(new Tuple<int, string>(28, "Tank Missing Delivery Ticket Warning"));
                aa02.Item2.Add(new Tuple<int, string>(29, "Tank or Line Gross Leak Alarm"));
                alarm_Type_Number_Mapping.Add(aa02);



                var aa03_04_07_08_12_13 = new Tuple<int[], List<Tuple<int, string>>>(new int[] { 3, 4, 7, 8, 12, 13 },
                    new List<Tuple<int, string>>());
                aa03_04_07_08_12_13.Item2.Add(new Tuple<int, string>(2, "Sensor Setup Data Warning"));
                aa03_04_07_08_12_13.Item2.Add(new Tuple<int, string>(3, "Sensor Fuel Alarm"));
                aa03_04_07_08_12_13.Item2.Add(new Tuple<int, string>(4, "Sensor Out Alarm"));
                aa03_04_07_08_12_13.Item2.Add(new Tuple<int, string>(5, "Sensor Short Alarm"));
                aa03_04_07_08_12_13.Item2.Add(new Tuple<int, string>(6, "Sensor Water Alarm"));
                aa03_04_07_08_12_13.Item2.Add(new Tuple<int, string>(7, "Sensor Water Out Alarm"));
                aa03_04_07_08_12_13.Item2.Add(new Tuple<int, string>(8, "Sensor High Liquid Alarm"));
                aa03_04_07_08_12_13.Item2.Add(new Tuple<int, string>(9, "Sensor Low Liquid Alarm"));
                aa03_04_07_08_12_13.Item2.Add(new Tuple<int, string>(10, "Sensor Liquid Warning"));
                alarm_Type_Number_Mapping.Add(aa03_04_07_08_12_13);



                var aa05 = new Tuple<int[], List<Tuple<int, string>>>(new int[] { 5 },
                    new List<Tuple<int, string>>());
                aa05.Item2.Add(new Tuple<int, string>(1, "Input Setup Data Warning"));
                aa05.Item2.Add(new Tuple<int, string>(2, "Input Normal"));
                aa05.Item2.Add(new Tuple<int, string>(3, "Input Alarm"));
                alarm_Type_Number_Mapping.Add(aa05);



                var aa06 = new Tuple<int[], List<Tuple<int, string>>>(new int[] { 6 }, new List<Tuple<int, string>>());
                aa06.Item2.Add(new Tuple<int, string>(1, "VLLD "));
                aa06.Item2.Add(new Tuple<int, string>(2, "Tank Leak Alarm"));
                aa06.Item2.Add(new Tuple<int, string>(3, "Tank High Water Alarm"));
                aa06.Item2.Add(new Tuple<int, string>(4, "Tank Overfill Alarm"));
                aa06.Item2.Add(new Tuple<int, string>(5, "Tank Low Product Alarm"));
                aa06.Item2.Add(new Tuple<int, string>(6, "Tank Sudden Loss Alarm"));
                aa06.Item2.Add(new Tuple<int, string>(7, "Tank High Product Alarm"));
                aa06.Item2.Add(new Tuple<int, string>(8, "Tank Invalid Fuel Level Alarm"));
                aa06.Item2.Add(new Tuple<int, string>(9, "Tank Probe Out Alarm"));
                aa06.Item2.Add(new Tuple<int, string>(10, "Tank High Water Warning"));
                aa06.Item2.Add(new Tuple<int, string>(11, "Tank Delivery Needed Warning"));
                aa06.Item2.Add(new Tuple<int, string>(12, "Tank Maximum Product Alarm"));
                aa06.Item2.Add(new Tuple<int, string>(13, "Tank Gross Leak Test Fail Alarm"));
                aa06.Item2.Add(new Tuple<int, string>(14, "Tank Periodic Leak Test Fail Alarm"));
                aa06.Item2.Add(new Tuple<int, string>(15, "Tank Annual Leak Test Fail Alarm"));
                aa06.Item2.Add(new Tuple<int, string>(16, "Tank Periodic Test Needed Warning"));
                aa06.Item2.Add(new Tuple<int, string>(17, "Tank Annual Test Needed Warning"));
                aa06.Item2.Add(new Tuple<int, string>(18, "Tank Periodic Test Needed Alarm"));
                aa06.Item2.Add(new Tuple<int, string>(19, "Tank Annual Test Needed Alarm"));
                aa06.Item2.Add(new Tuple<int, string>(20, "Tank Leak Test Active"));
                aa06.Item2.Add(new Tuple<int, string>(21, "Tank No CSLD Idle Time Warning"));
                aa06.Item2.Add(new Tuple<int, string>(22, "Tank Siphon Break Active Warning"));
                aa06.Item2.Add(new Tuple<int, string>(23, "Tank CSLD Rate Increase Warning"));
                aa06.Item2.Add(new Tuple<int, string>(24, "Tank AccuChart Calibration Warning"));
                aa06.Item2.Add(new Tuple<int, string>(25, "Tank HRM Reconciliation Warning"));
                aa06.Item2.Add(new Tuple<int, string>(26, "Tank HRM Reconciliation Alarm"));
                aa06.Item2.Add(new Tuple<int, string>(27, "Tank Clod Temperature Warning"));
                aa06.Item2.Add(new Tuple<int, string>(28, "Tank Missing Delivery Ticket Warning"));
                alarm_Type_Number_Mapping.Add(aa06);



                var aa14 = new Tuple<int[], List<Tuple<int, string>>>(new int[] { 14 },
                    new List<Tuple<int, string>>());
                aa14.Item2.Add(new Tuple<int, string>(1, "Autodial Setup Data Warning"));
                aa14.Item2.Add(new Tuple<int, string>(2, "Autodial Failed Alarm"));
                aa14.Item2.Add(new Tuple<int, string>(3, "Autodial Service Report Warning"));
                aa14.Item2.Add(new Tuple<int, string>(4, "Autodial Alarm Clear Warning"));
                aa14.Item2.Add(new Tuple<int, string>(5, "Autodial Delivery Report Warning"));
                alarm_Type_Number_Mapping.Add(aa14);



                var aa18_19 = new Tuple<int[], List<Tuple<int, string>>>(new int[] { 18, 19 },
                    new List<Tuple<int, string>>());
                aa18_19.Item2.Add(new Tuple<int, string>(2, "DIM Disabled Alarm"));
                aa18_19.Item2.Add(new Tuple<int, string>(3, "DIM Communication Failure Alarm"));
                aa18_19.Item2.Add(new Tuple<int, string>(4, "DIM Transaction Alarm"));
                alarm_Type_Number_Mapping.Add(aa18_19);



                var aa20 = new Tuple<int[], List<Tuple<int, string>>>(new int[] { 20 },
                   new List<Tuple<int, string>>());
                aa20.Item2.Add(new Tuple<int, string>(1, "BIR Setup Data Warning"));
                aa20.Item2.Add(new Tuple<int, string>(2, "BIR Threshold Alarm"));
                aa20.Item2.Add(new Tuple<int, string>(3, "BIR Close Shift Warning"));
                aa20.Item2.Add(new Tuple<int, string>(4, "BIR Close Daily Warning"));
                alarm_Type_Number_Mapping.Add(aa20);



                var aa21 = new Tuple<int[], List<Tuple<int, string>>>(new int[] { 21 },
                    new List<Tuple<int, string>>());
                aa21.Item2.Add(new Tuple<int, string>(1, "PLLD Setup Data Warning"));
                aa21.Item2.Add(new Tuple<int, string>(2, "PLLD Gross Test Fail Alarm"));
                aa21.Item2.Add(new Tuple<int, string>(3, "PLLD Anuual Test Fail Alarm"));
                aa21.Item2.Add(new Tuple<int, string>(4, "PLLD Periodic Test Needed Warning"));
                aa21.Item2.Add(new Tuple<int, string>(5, "PLLD Periodic Test Needed Alarm"));
                aa21.Item2.Add(new Tuple<int, string>(6, "PLLD Sensor Open Alarm"));
                aa21.Item2.Add(new Tuple<int, string>(7, "PLLD High Pressure Alarm"));
                aa21.Item2.Add(new Tuple<int, string>(8, "PLLD Shutdown Alarm"));
                aa21.Item2.Add(new Tuple<int, string>(9, "PLLD High Pressure Warning"));
                aa21.Item2.Add(new Tuple<int, string>(10, "PLLD Continuous Handle On Warning"));
                aa21.Item2.Add(new Tuple<int, string>(11, "PLLD Periodic Test Fail Alarm"));
                aa21.Item2.Add(new Tuple<int, string>(12, "PLLD Annual Test Needed Warning"));
                aa21.Item2.Add(new Tuple<int, string>(13, "PLLD Annual Test Needed Alarm"));
                aa21.Item2.Add(new Tuple<int, string>(14, "PLLD Low Pressure Alarm"));
                aa21.Item2.Add(new Tuple<int, string>(15, "PLLD Sensor Short Alarm"));
                aa21.Item2.Add(new Tuple<int, string>(16, "PLLD Continuous Handle On Alarm"));
                aa21.Item2.Add(new Tuple<int, string>(17, "PLLD Fuel Out Alarm"));
                aa21.Item2.Add(new Tuple<int, string>(18, "PLLD Line Equipment Alarm"));
                alarm_Type_Number_Mapping.Add(aa21);



                var aa26 = new Tuple<int[], List<Tuple<int, string>>>(new int[] { 26 },
                    new List<Tuple<int, string>>());
                aa26.Item2.Add(new Tuple<int, string>(1, "WPLLD Setup Data Warning"));
                aa26.Item2.Add(new Tuple<int, string>(2, "WPLLD Gross Test Fail Alarm"));
                aa26.Item2.Add(new Tuple<int, string>(3, "WPLLD Anuual Test Fail Alarm"));
                aa26.Item2.Add(new Tuple<int, string>(4, "WPLLD Periodic Test Needed Warning"));
                aa26.Item2.Add(new Tuple<int, string>(5, "WPLLD Periodic Test Needed Alarm"));
                aa26.Item2.Add(new Tuple<int, string>(6, "WPLLD Sensor Open Alarm"));
                aa26.Item2.Add(new Tuple<int, string>(7, "WPLLD High Pressure Alarm"));
                aa26.Item2.Add(new Tuple<int, string>(8, "WPLLD Shutdown Alarm"));
                aa26.Item2.Add(new Tuple<int, string>(9, "WPLLD High Pressure Warning"));
                aa26.Item2.Add(new Tuple<int, string>(10, "WPLLD Continuous Handle On Warning"));
                aa26.Item2.Add(new Tuple<int, string>(11, "WPLLD Periodic Test Fail Alarm"));
                aa26.Item2.Add(new Tuple<int, string>(12, "WPLLD Annual Test Needed Warning"));
                aa26.Item2.Add(new Tuple<int, string>(13, "WPLLD Annual Test Needed Alarm"));
                aa26.Item2.Add(new Tuple<int, string>(14, "WPLLD Low Pressure Alarm"));
                aa26.Item2.Add(new Tuple<int, string>(15, "WPLLD Sensor Short Alarm"));
                aa26.Item2.Add(new Tuple<int, string>(16, "WPLLD Continuous Handle On Alarm"));
                aa26.Item2.Add(new Tuple<int, string>(17, "WPLLD Fuel Out Alarm"));
                aa26.Item2.Add(new Tuple<int, string>(18, "WPLLD Line Equipment Alarm"));
                alarm_Type_Number_Mapping.Add(aa26);



                var aa99 = new Tuple<int[], List<Tuple<int, string>>>(new int[] { 99 },
                    new List<Tuple<int, string>>());
                aa99.Item2.Add(new Tuple<int, string>(1, "Externally Dectected Communication Alarm"));
                aa99.Item2.Add(new Tuple<int, string>(2, "Communications - Data Reception Timeout"));
                aa99.Item2.Add(new Tuple<int, string>(3, "Communications - Failed Checksum"));
                aa99.Item2.Add(new Tuple<int, string>(4, "Communications - Parity Error"));
                aa99.Item2.Add(new Tuple<int, string>(5, "Modem - Line Busy"));
                aa99.Item2.Add(new Tuple<int, string>(6, "Modem -  No Answer"));
                aa99.Item2.Add(new Tuple<int, string>(7, "Modem -  No Carrier"));
                aa99.Item2.Add(new Tuple<int, string>(8, "Modem -  No Dial Tone"));
                aa99.Item2.Add(new Tuple<int, string>(9, "Modem -  Modem Error"));
                aa99.Item2.Add(new Tuple<int, string>(10, "Modem -  Modem Not Responding"));
                aa99.Item2.Add(new Tuple<int, string>(11, "Modem -  Port Not Available"));
                aa99.Item2.Add(new Tuple<int, string>(12, "Polling - Could Not Update Queue"));
                aa99.Item2.Add(new Tuple<int, string>(13, "Polling - Invalid Data Type Requested"));
                alarm_Type_Number_Mapping.Add(aa99);
            }

            private byte[] bytes;
            public QuerySystemStatusReportData(byte[] bytes)
            {
                this.bytes = bytes;
            }

            public int? TankNumber
            {
                get
                {
                    var r = int.Parse(Encoding.ASCII.GetString(this.bytes.Skip(4).Take(2).ToArray()));
                    return r;
                }
            }

            public Alarm_Warning_Category? Alarm_Warning_Category
            {
                get
                {
                    var r = (Alarm_Warning_Category)Enum.Parse(
                        typeof(Alarm_Warning_Category),
                        Encoding.ASCII.GetString(this.bytes.Take(2).ToArray()));
                    return r;
                }
            }

            public string AlarmInfo
            {
                get
                {
                    var alarmTypeNumberInt = int.Parse(Encoding.ASCII.GetString(this.bytes.Skip(2).Take(2).ToArray()));
                    return alarm_Type_Number_Mapping.FirstOrDefault(m => m.Item1.Contains((int)this.Alarm_Warning_Category))
                         ?.Item2.FirstOrDefault(f => f.Item1 == alarmTypeNumberInt).Item2;
                }
            }
        }
    }
}