using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace LFP_Manager.DataStructure
{
    public class CommConfig
    {
        public string AppPath;
        public string mSN;

        public int CommType;

        public int TargetModelIndex;

        public string SnmpIP;
        public int SnmpModelIndex;
        public int SnmpMdQty;

        public string UartPort;
        public int UartBaudrate;
        public int UartModelIndex;

        public int CanDevice;
        public int CanIndex;
        public int CanNo;
        public int CanBaudrate;

        public int DbLogPeriod;

        public int CbTestGap;
        public int CbTestTime;

        public CommConfig()
        {
            CommType = 0;
            TargetModelIndex = 0;
            SnmpIP = "";
            SnmpModelIndex = 0;
            SnmpMdQty = 0;
            UartPort = "";
            UartBaudrate = 0;
            UartModelIndex = 0;
            CanDevice = 0;
            CanIndex = 0;
            CanNo = 0;
            CanBaudrate = 0;

            DbLogPeriod = 5;

            CbTestGap = 1500;
            CbTestTime = 3000;
        }
    }

    public class TMinMax
    {
        public short value;
        public short num;

        public TMinMax()
        {
            value = 0;
            num = 0;
        }
    }

    public class DeviceSystemTotalData
    {
        public bool CommFail;

        public DeviceValueTotalData ValueData;
        public DeviceStatusTotalData StatusData;
        public DeviceAvgData AvgData;

        public DeviceSystemTotalData()
        {
            CommFail = false;
            ValueData = new DeviceValueTotalData();
            StatusData = new DeviceStatusTotalData();
            AvgData = new DeviceAvgData();
        }
    }

    public class DeviceSystemData
    {
        public int mNo;
        public int cellQty;
        public int tempQty;
        public UInt32 heatbeat;
        public int OneBuffTime;
        public int AllBuffTime;
        public bool CommFail;
        public bool ShelfCommFail;
        public DateTime LastRxTime;

        public DeviceValueData ValueData;
        public DeviceAvgData AvgData;
        public DeviceStatusData StatusData;
        public DeviceParamData ParamData;
        public DeviceCalibration CalibriationData;

        public DeviceInforation Information;
        public DeviceSystemData()
        {
            mNo = 0;
            heatbeat = 0;
            OneBuffTime = 0;
            AllBuffTime = 0;
            CommFail = false;
            ShelfCommFail = false;
            LastRxTime = new DateTime();

            ValueData = new DeviceValueData();
            AvgData = new DeviceAvgData();
            StatusData = new DeviceStatusData();
            ParamData = new DeviceParamData();
            CalibriationData = new DeviceCalibration();

            Information = new DeviceInforation();
        }
    }

    public class DeviceValueTotalData
    {
        public short TotalVoltage;
        public short TotalCurrent;
        public short TotalSOC;
        public short TotalTemp;

        public DeviceValueTotalData()
        {
            TotalVoltage = 0;
            TotalCurrent = 0;
            TotalSOC = 0;
            TotalTemp = 0;
        }
    }

    public class DeviceValueData
    {
        public byte[] fw_ver;

        public short voltageOfPack;
        public short current;
        public short averageCurrent;
        public short rSOC;

        public ushort[] CellVoltage;
        public short[] CellTemperature;

        public short CpuTemperature;
        public short FetTemperature;

        public short remainingCapacity;
        public short stateOfHealth;
        public short cycleCount;
        public short fullChargeCapacity;
        public short designedCapacity;
        public DeviceValueData()
        {
            fw_ver = new byte[4];

            voltageOfPack = 0;
            current = 0;
            averageCurrent = 0;
            rSOC = 0;

            CellVoltage = new ushort[csConstData.SystemInfo.MAX_MODULE_CELL_SIZE];
            CellTemperature = new short[csConstData.SystemInfo.MAX_MODULE_TEMP_SIZE];

            CpuTemperature = 0;
            FetTemperature = 0;

            remainingCapacity = 0;
            stateOfHealth = 0;
            cycleCount = 0;
            fullChargeCapacity = 0;
            designedCapacity = 0;
        }
    }

    public class DeviceAvgData
    {
        public ushort maxCellVoltage;
        public ushort minCellVoltage;
        public ushort avgCellVoltage;
        public ushort diffCellVoltage;
        public short maxCellNum;
        public short minCellNum;
        public short maxTemp;
        public short minTemp;
        public short avgTemp;
        public short diffTemp;
        public short maxTempNum;
        public short minTempNum;
        public DeviceAvgData()
        {
            maxCellVoltage = 0;
            minCellVoltage = 0;
            avgCellVoltage = 0;
            diffCellVoltage = 0;
            maxCellNum = 0;
            minCellNum = 0;
            maxTemp = 0;
            minTemp = 0;
            avgTemp = 0;
            diffTemp = 0;
            maxTempNum = 0;
            minTempNum = 0;
        }
    }

    public class DeviceStatusTotalData
    {
        public short batteryStatus;
        public short warning;
        public short protect;
        public short status;

        public DeviceStatusTotalData()
        {
            batteryStatus = 0;
            warning = 0;
            protect = 0;
            status = 0;
        }
    }

    public class DeviceStatusData
    {
        public short batteryStatusA;
        public short batteryStatusB;
        public short warning;
        public short protect;
        public short protect1;
        public short status;
        public short alarm;
        public short relayStatus;
        public uint cellBallanceStatusLv;
        public uint cellBallanceStatusHv;
        public ushort cellBalanceValue;

        public uint BalanceEnable;
        public uint BalanceMode;

        public short cellBalanceInterval;
        public short cellBalanceEndGap;
        public short cellBalanceFlag;
        public DeviceStatusData()
        {
            batteryStatusA = 0;
            batteryStatusB = 0;
            warning = 0;
            protect = 0;
            protect1 = 0;
            status = 0;
            alarm = 0;
            relayStatus = 0;
            cellBallanceStatusLv = 0;
            cellBallanceStatusHv = 0;
            cellBalanceValue = 0;
            cellBalanceInterval = 0;
            cellBalanceEndGap = 0;
            cellBalanceFlag = 0;
        }
    }

    public class DeviceCommStatus
    {
        public DateTime LastRxTime;
        public bool CommFail;
        public DeviceCommStatus()
        {
            LastRxTime = new DateTime();
            CommFail = false;
        }
    }

    public class DeviceParamData
    {
        public short CellOverVoltageTrip;
        public short CellOverVoltageWarning;
        public short CellOverVoltageRelease;
        public short CellUnderVoltageTrip;
        public short CellUnderVoltageWarning;
        public short CellUnderVoltageRelease;

        public short SysOverVoltageTrip;
        public short SysOverVoltageWarning;
        public short SysOverVoltageRelease;
        public short SysUnderVoltageTrip;
        public short SysUnderVoltageWarning;
        public short SysUnderVoltageRelease;

        public short ChaHighTempTrip;
        public short ChaHighTempWarning;
        public short ChaHighTempRelease;
        public short ChaLowTempTrip;
        public short ChaLowTempWarning;
        public short ChaLowTempRelease;
        public short DchHighTempTrip;
        public short DchHighTempWarning;
        public short DchHighTempRelease;
        public short DchLowTempTrip;
        public short DchLowTempWarning;
        public short DchLowTempRelease;

        public short ChaOverCurrentTrip;
        public short ChaOverCurrentWarning;
        public short ChaOverCurrentRelease;
        public short DchOverCurrentTrip;
        public short DchOverCurrentWarning;
        public short DchOverCurrentRelease;

        public short LowSocTrip;
        public short LowSocWarning;
        public short LowSocRelease;

        public short CellVoltageDifferenceTrip;
        public short CellVoltageDifferenceWarning;
        public short CellVoltageDifferenceRelease;
        public short CellVoltageDifferenceTime;

        public short DefalutParamOption;
        public short DefalutParamAll;
        public DeviceParamData()
        {
            CellOverVoltageTrip = 0;
            CellOverVoltageWarning = 0;
            CellOverVoltageRelease = 0;
            CellUnderVoltageTrip = 0;
            CellUnderVoltageWarning = 0;
            CellUnderVoltageRelease = 0;

            SysOverVoltageTrip = 0;
            SysOverVoltageWarning = 0;
            SysOverVoltageRelease = 0;
            SysUnderVoltageTrip = 0;
            SysUnderVoltageWarning = 0;
            SysUnderVoltageRelease = 0;

            ChaHighTempTrip = 0;
            ChaHighTempWarning = 0;
            ChaHighTempRelease = 0;
            ChaLowTempTrip = 0;
            ChaLowTempWarning = 0;
            ChaLowTempRelease = 0;
            DchHighTempTrip = 0;
            DchHighTempWarning = 0;
            DchHighTempRelease = 0;
            DchLowTempTrip = 0;
            DchLowTempWarning = 0;
            DchLowTempRelease = 0;

            ChaOverCurrentTrip = 0;
            ChaOverCurrentWarning = 0;
            ChaOverCurrentRelease = 0;
            DchOverCurrentTrip = 0;
            DchOverCurrentWarning = 0;
            DchOverCurrentRelease = 0;

            LowSocTrip = 0;
            LowSocWarning = 0;
            LowSocRelease = 0;

            CellVoltageDifferenceTrip = 0;
            CellVoltageDifferenceWarning = 0;
            CellVoltageDifferenceRelease = 0;
            CellVoltageDifferenceTime = 0;

            DefalutParamOption = 0;
            DefalutParamAll = 0;
        }
    }

    public class DeviceCalibration
    {
        public CellVoltageCalib CellVoltge;
        public SystemVoltageCalib SystemVoltage;
        public ForcedBalControl ForcedBalancing;
        public ForcedBalControl2 ForcedBalancing2; // For PR-57150
        public BatteryParameter Battery;
        public CurrentCalib Current;
        public SystemInfor SystemInfo;
        public SocCalibration SocCalib;
        public TCbParam CbParam;

        public DeviceInforation InvData;

        public short CellBalancingVoltage;
        public short CellBalancingVoltageInterval;
        public short CellBalancingVoltageEndGap;

        public DeviceCalibration()
        {
            CellVoltge = new CellVoltageCalib();
            SystemVoltage = new SystemVoltageCalib();
            ForcedBalancing = new ForcedBalControl();
            ForcedBalancing2 = new ForcedBalControl2(); // For PR-57150
            Battery = new BatteryParameter();
            Current = new CurrentCalib();
            SystemInfo = new SystemInfor();
            SocCalib = new SocCalibration();
            CbParam = new TCbParam();

            InvData = new DeviceInforation();

            CellBalancingVoltage = 0;
            CellBalancingVoltageInterval = 0;
            CellBalancingVoltageEndGap = 0;
        }
        public DeviceCalibration DeepCopy()
        {
            DeviceCalibration newCopy = new DeviceCalibration
            {
                CellVoltge = CellVoltge,
                SystemVoltage = SystemVoltage,
                ForcedBalancing = ForcedBalancing.DeepCopy(),
                Battery = Battery,
                Current = Current,
                SystemInfo = SystemInfo,
                SocCalib = SocCalib,
                CbParam = CbParam.DeepCopy(),

                InvData = InvData,

                CellBalancingVoltage = CellBalancingVoltage,
                CellBalancingVoltageInterval = CellBalancingVoltageInterval,
                CellBalancingVoltageEndGap = CellBalancingVoltageEndGap,
            };
            return newCopy;
        }

    }

    public class DeviceInforation
    {
        public UInt32 ManufactureDate;
        public byte[] pcb_sn;
        public byte[] module_sn;
        public DeviceInforation()
        {
            ManufactureDate = 0;
            pcb_sn = new byte[16];
            module_sn = new byte[32];
        }
    }

    public class CellVoltageCalib
    {
        public short CvOffsetLow;
        public short CvOffsetHigh;
        public CellVoltageCalib()
        {
            CvOffsetLow = 0;
            CvOffsetHigh = 0;
        }
    }

    public class SystemVoltageCalib
    {
        public short Calibration_K;
        public short Calibration_B;
        public SystemVoltageCalib()
        {
            Calibration_K = 0;
            Calibration_B = 0;
        }
    }

    public class ForcedBalControl
    {
        public short Control;
        public short CellNo;
        public bool AutoB;
        public bool DCP;
        public ForcedBalControl()
        {
            Control = 0;
            CellNo = 0;
            AutoB = false;
            DCP = false;
        }
        public ForcedBalControl DeepCopy()
        {
            ForcedBalControl newCopy = new ForcedBalControl()
            {
                Control = Control,
                CellNo = CellNo,
                AutoB = AutoB,
                DCP = DCP
            };
            return newCopy;
        }
    }

    public class ForcedBalControl2
    {
        public int Control;
        public int CellNo;
        public int Mode;
        public int Enable;
        public ForcedBalControl2()
        {
            Control = 0;
            CellNo = 0;
            Mode = 0;
            Enable = 0;
        }
        public ForcedBalControl2 DeepCopy()
        {
            ForcedBalControl2 newCopy = new ForcedBalControl2()
            {
                Control = Control,
                CellNo = CellNo,
                Mode = Mode,
                Enable = Enable
            };
            return newCopy;
        }
    }

    public class BatteryParameter
    {
        public short CellQty;
        public short TempQty;
        public UInt32 Capacity;
        public BatteryParameter()
        {
            CellQty = 0;
            TempQty = 0;
            Capacity = 0;
        }
    }

    public class CurrentCalib
    {
        public short SelectSubItem;
        public short ShuntRange;
        public short CurrentZero;
        public short VoltageZero;
        public Int32 Calibration_K;
        public short ChaAndDchSelect;
        public short ChargeOption;
        public CurrentCalib()
        {
            SelectSubItem = 0;
            ShuntRange = 0;
            CurrentZero = 0;
            VoltageZero = 0;
            Calibration_K = 0;
            ChaAndDchSelect = 0;
            ChargeOption = 0;
        }
    }

    public class SystemInfor
    {
        //public short Id;
        public DateTime devTime;
        public UInt16 devAddr;
        public SystemInfor()
        {
            devTime = new DateTime();
            devAddr = 0;
        }
    }

    public class SocCalibration
    {
        public short CellNo;
        public short SocValue;
        public SocCalibration()
        {
            CellNo = 0;
            SocValue = 0;
        }
    }

    public class TCbParam
    {
        public short Threadhold;
        public short Window;
        public short Min;
        public short Interval;
        public TCbParam()
        {
            Threadhold = 0;
            Window = 0;
            Min = 0;
            Interval = 0;
        }
        public TCbParam DeepCopy()
        {
            TCbParam newCopy = new TCbParam
            {
                Threadhold = Threadhold, 
                Window = Window, 
                Min = Min, 
                Interval = Interval
            };
            return newCopy;
        }
    }

    public class DataFunction
    {
        public static void DataInit(ref DeviceSystemData sData, ref CommConfig sConfig)
        {
            sData.ShelfCommFail = true;

            switch (sConfig.TargetModelIndex)
            {
                case 0:             // PR-57150
                    sData.cellQty = 18;
                    sData.tempQty = 6;
                    break;
                case 1:             // PR-64150
                    sData.cellQty = 20;
                    sData.tempQty = 8;
                    break;
                case 2:             // LFPM-57080
                    sData.cellQty = 18;
                    sData.tempQty = 6;
                    break;
                case 3:             // PR-102150
                    sData.cellQty = 32;
                    sData.tempQty = 8;
                    break;
                case 4:             // PR-115300
                    sData.cellQty = 36;
                    sData.tempQty = 16;
                    break;
                case 5:             // PR-67150
                    sData.cellQty = 21;
                    sData.tempQty = 8;
                    break;
                default:
                    sData.cellQty = 18;
                    sData.tempQty = 6;
                    break;
            }

            for (int j = 0; j < csConstData.SystemInfo.MAX_MODULE_CELL_SIZE; j++)
            {
                sData.ValueData.CellVoltage[j] = 0;
            }
            for (int j = 0; j < csConstData.SystemInfo.MAX_MODULE_TEMP_SIZE; j++)
            {
                sData.ValueData.CellTemperature[j] = 0;
            }
            sData.ValueData.voltageOfPack = 0;
            sData.ValueData.current = 0;
            sData.ValueData.rSOC = 0;
            sData.AvgData.maxCellVoltage = 0;
            sData.AvgData.minCellVoltage = 0;
            sData.AvgData.avgCellVoltage = 0;
            sData.AvgData.maxTemp = 0;
            sData.AvgData.minTemp = 0;
            sData.AvgData.avgTemp = 0;
            sData.heatbeat = 0;
            sData.StatusData.warning = 0;
            sData.StatusData.protect = 0;
        }
    }
    public class TCanTxBuff
    {
        private const int BuffMax = 4096;
        public int InPos;
        public int OutPos;
        public TCanTRxData[] Buf;
        public TCanTxBuff()
        {
            InPos = 0;
            OutPos = 0;
            Buf = new TCanTRxData[BuffMax];
            for (int i = 0; i < BuffMax; i++)
            {
                Buf[i] = new TCanTRxData();
            }
        }

        public void PutBuff(TCanTRxData CanTxData)
        {
            if (CanTxData != null)
            {
                Buf[InPos++] = CanTxData.DeepCopy();
                InPos %= BuffMax;
            }
        }
        public TCanTRxData GetBuff()
        {
            TCanTRxData result = null;

            if (InPos != OutPos)
            {
                result = Buf[OutPos++].DeepCopy();
                OutPos %= BuffMax;
            }
            return result;
        }
    }
    public class TCanTRxData
    {
        public int type;
        public UInt32 exid;
        public byte[] data;

        public TCanTRxData()
        {
            type = 0;
            exid = 0;
            data = new byte[8];
        }
        public TCanTRxData DeepCopy()
        {
            TCanTRxData newCopy = new TCanTRxData
            {
                exid = exid
            };
            for (int i = 0; i < 8; i++)
            {
                newCopy.data[i] = data[i];
            }
            return newCopy;
        }
    }

}
