using AwInitilizer.Assist;
using CsuWebApiLib;
using PhihongEv.Lib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AwInitilizer.Procedure.FourGenModuleCheck
{
    public enum ErrorType
    {
        None,
        ConnectFail,
        VersionReadFail,
        VersionMismatch,
        SimStatusReadFail,
        SimStatusMismatch,
        IccidMistach,
        ImsiMistach,
    }

    public enum LogEvent
    {
        FourgenSocketConnect,
        FourgenModuleVersion,
        SubFourgenModuleVersion,
        SimStatus,
        SimICCID,
        SimIMSI,
        SubSimStatus,
        SubSimICCID,
        SubSimIMSI
    }

    public class FourGenModuleCheckProcedure : ProcedureBase
    {
        public ErrorType Error { get; set; } = ErrorType.None;

        private ProcedureLog.LogWriter<FourGenModuleCheckProcedure, LogEvent> LogWriter;

        private readonly static Dictionary<LogEvent, string> ReportDict = new Dictionary<LogEvent, string>()
        {
            { LogEvent.FourgenSocketConnect, "FourgenSocketConnect" },
            { LogEvent.FourgenModuleVersion, "FourgenModuleVersion" },
            { LogEvent.SubFourgenModuleVersion, "SubFourgenModuleVersion" },
            { LogEvent.SimStatus, "SimStatus" },
            { LogEvent.SimICCID, "SimICCID" },
            { LogEvent.SimIMSI, "SimIMSI" },
            { LogEvent.SubSimStatus, "SubSimStatus" },
            { LogEvent.SubSimICCID, "SubSimICCID" },
            { LogEvent.SubSimIMSI, "SubSimIMSI" },
        };

        private readonly static Dictionary<LogEvent, string> LogDict = new Dictionary<LogEvent, string>()
        {
            { LogEvent.FourgenSocketConnect, "EVSE connect {0}" },
            { LogEvent.FourgenModuleVersion, "Read 4G Module version : {0}" },
            { LogEvent.SubFourgenModuleVersion, "Read sub 4G Module version : {0}" },
            { LogEvent.SimStatus, "Get sim instert status {0}" },
            { LogEvent.SimICCID, "Get Sim ICCID : {0}" },
            { LogEvent.SimIMSI, "Get Sim IMSI : {0}" },
            { LogEvent.SubSimStatus, "Get sub sim instert status {0}" },
            { LogEvent.SubSimICCID, "Get sub Sim ICCID : {0}" },
            { LogEvent.SubSimIMSI, "Get sub Sim IMSI : {0}" },
        };

        public FourGenModuleCheckProcedure() : base()
        {
            Name = "4G Check";
            Content = "Check 4G module version and SIM card information matches user input";

            LogWriter = new ProcedureLog.LogWriter<FourGenModuleCheckProcedure, LogEvent>(this)
            {
                ReportPair = ReportDict,
                LogPair = LogDict
            };
        }

        internal override async Task<bool> Run()
        {
            //if (UpdateData.SystemID.ModelName.Type.Code == "DD")
            //{
            //    LogWriter.Log("4G not supported, skip procedure");

            //    return true;
            //}

            //if (!UpdateData.SystemID.ModelName.Network.Description.Contains("4G"))
            //if (!UpdateData.SystemID.ModelName.Network.SupportTelecom)
            if (UpdateData.SystemID.ModelName.GetTelecomCnt() == 0)
            {
                //if does not support 4G then end init
                LogWriter.Log("4G not supported, skip procedure");

                return true;
            }

            //Logger.Print("Connecting to EVSE");
            //int pollingCnt;
            //bool response;
            //for (pollingCnt = 0; pollingCnt < 56; pollingCnt++)
            //{
            //    await Task.Delay(TimeSpan.FromSeconds(15));
            //    response = await ChekCsuBootCompelete();
            //    if (response)
            //        break;
            //}

            //LogWriter.Log(string.Format("EVSE connet elapsed minute(s) : {0}, Expect:<16", (pollingCnt * 0.25) + 2));

            ////timeout
            //if (pollingCnt >= 56)
            //{
            //    LogWriter.Report(LogEvent.FourgenSocketConnect, "fail", isError: true);
            //    Error = ErrorType.ConnectFail;

            //    return false;
            //}

            //if (!await base.CheckAndCreateSocket())
            //{
            //    LogWriter.Report(LogEvent.FourgenSocketConnect, "fail", isError: true);
            //    Error = ErrorType.ConnectFail;

            //    return false;
            //}
            //LogWriter.Report(LogEvent.FourgenSocketConnect, "success");

            //var fourthGenModuleVersion = await serialPortocol.GetFourGenModuleVersion();
            string fourthGenModuleVersion = null;
            EvApiResult<string> getfourthGenModuleVersion = null;
            int retryCnt = 0;
            do
            {
                getfourthGenModuleVersion = await EvApi.GetTelcomModemFwRev();
                fourthGenModuleVersion = getfourthGenModuleVersion.Result;

                if (!string.IsNullOrEmpty(fourthGenModuleVersion) || retryCnt >= 5)
                {
                    break;
                }
                await Task.Delay(TimeSpan.FromMinutes(2));
                retryCnt++;
            }
            while (true);
            //LogWriter.Report(LogEvent.FourgenModuleVersion, fourthGenModuleVersion);

            if (string.IsNullOrEmpty(fourthGenModuleVersion))
            {
                Error = ErrorType.VersionReadFail;
                LogWriter.Log("4G module version read error");
                LogWriter.Report(LogEvent.FourgenModuleVersion, "empty", isError: true);
                return false;
            }

            LogWriter.Log(string.Format("Read 4G Module version : {0} , Expect:{1}", fourthGenModuleVersion, UpdateData.FourGenModuleVersion));

            if (!fourthGenModuleVersion.ToLower().StartsWith(UpdateData.FourGenModuleVersion.ToLower()))
            {
                Error = ErrorType.VersionMismatch;
                LogWriter.Report(LogEvent.FourgenModuleVersion, fourthGenModuleVersion, isError: true);
                return false;
            }

            LogWriter.Report(LogEvent.FourgenModuleVersion, fourthGenModuleVersion);

            //if (UpdateData.SystemID.ModelName.Network.SupportSubTelecom)
            if (UpdateData.SystemID.ModelName.GetTelecomCnt() > 1)
            {
                //var fourthGenModuleVersion = await serialPortocol.GetFourGenModuleVersion();
                getfourthGenModuleVersion = await EvApi.GetTelcomSubModemFwRev();
                fourthGenModuleVersion = getfourthGenModuleVersion.Result;
                //LogWriter.Report(LogEvent.FourgenModuleVersion, fourthGenModuleVersion);

                //int retryCnt = 0;
                retryCnt = 0;
                while (string.IsNullOrEmpty(fourthGenModuleVersion) && retryCnt < 30)
                {
                    retryCnt++;
                    await Task.Delay(TimeSpan.FromSeconds(10));
                    getfourthGenModuleVersion = await EvApi.GetTelcomSubModemFwRev();
                    fourthGenModuleVersion = getfourthGenModuleVersion.Result;
                }
                LogWriter.Log($"Get sub sim version retry {retryCnt}");


                if (string.IsNullOrEmpty(fourthGenModuleVersion))
                {
                    Error = ErrorType.VersionReadFail;
                    LogWriter.Log("sub 4G module version read error");
                    LogWriter.Report(LogEvent.SubFourgenModuleVersion, "empty", isError: true);
                    return false;
                }

                LogWriter.Log(string.Format("Read sub 4G Module version : {0} , Expect:{1}", fourthGenModuleVersion, UpdateData.SubFourGenModuleVersion));

                if (!fourthGenModuleVersion.ToLower().StartsWith(UpdateData.SubFourGenModuleVersion.ToLower()))
                {
                    Error = ErrorType.VersionMismatch;
                    LogWriter.Report(LogEvent.SubFourgenModuleVersion, fourthGenModuleVersion, isError: true);
                    return false;
                }

                LogWriter.Report(LogEvent.SubFourgenModuleVersion, fourthGenModuleVersion);
            }


            //var simstatus = await serialPortocol.GetSimStatus();
            var getResult = await EvApi.GetTelcomSimStatus();
            var simstatus = getResult.Result;
            string simstatusString;

            if (simstatus == null)
            {
                simstatusString = "unknown";
                //LogWriter.Report(LogEvent.SimStatus, "unknown");
            }
            else if (simstatus.IsInstalled)
            {
                simstatusString = "inserted";
                //LogWriter.Report(LogEvent.SimStatus, "inserted");
            }
            else
            {
                simstatusString = "none";
                //LogWriter.Report(LogEvent.SimStatus, "none");
            }

            if (simstatus == null)
            {
                Error = ErrorType.SimStatusReadFail;
                LogWriter.Report(LogEvent.SimStatus, simstatusString, isError: true);
                return false;
            }
            LogWriter.Log(string.Format("Get Sim Status : {0} , Expect:{1}", simstatus.IsInstalled ? "installed" : "uninstalled", UpdateData.IsSimInsert ? "installed" : "uninstalled"));

            if (simstatus.IsInstalled != UpdateData.IsSimInsert)
            {
                Error = ErrorType.SimStatusMismatch;
                LogWriter.Report(LogEvent.SimStatus, simstatusString, isError: true);
                return false;
            }
            LogWriter.Report(LogEvent.SimStatus, simstatusString);
            if (simstatus.IsInstalled)
            {
                //var iccidByteList = simstatus.ICCID.ToList();
                //iccidByteList.RemoveAll(x => x == 0x00);
                //var iccidBytes = iccidByteList.ToArray();

                //var imsiByteList = simstatus.IMSI.ToList();
                //imsiByteList.RemoveAll(x => x == 0x00);
                //var imsiBytes = imsiByteList.ToArray();


                //var ICCIDstring = Encoding.ASCII.GetString(iccidBytes).Trim();
                //var IMSIstring = Encoding.ASCII.GetString(imsiBytes).Trim();
                var ICCIDstring = simstatus.ICCID;
                var IMSIstring = simstatus.IMSI;

                //LogWriter.Report(LogEvent.SimICCID, ICCIDstring);
                //LogWriter.Report(LogEvent.SimIMSI, IMSIstring);

                LogWriter.Log(string.Format("Get Sim ICCID : {0} , Expect:{1}", ICCIDstring, UpdateData.SimICCID));
                LogWriter.Log(string.Format("Get Sim IMSI : {0} , Expect:{1}", IMSIstring, UpdateData.SimIMSI));

                if (ICCIDstring != UpdateData.SimICCID)
                {
                    LogWriter.Log("Sim card ICCID not match");
                    Error = ErrorType.IccidMistach;
                    LogWriter.Report(LogEvent.SimICCID, ICCIDstring, isError: true);
                    return false;
                }
                else
                {
                    LogWriter.Report(LogEvent.SimICCID, ICCIDstring);
                }

                if (IMSIstring != UpdateData.SimIMSI)
                {
                    LogWriter.Log("Sim card IMSI not match");
                    Error = ErrorType.ImsiMistach;
                    LogWriter.Report(LogEvent.SimIMSI, IMSIstring, isError: true);
                    return false;
                }
                else
                {
                    LogWriter.Report(LogEvent.SimIMSI, IMSIstring);
                }
            }
            else
            {
            }



            //if (!UpdateData.SystemID.ModelName.Network.SupportSubTelecom)
            if (UpdateData.SystemID.ModelName.GetTelecomCnt() > 1)
            {
                return true;
            }

            getResult = await EvApi.GetTelcomSubSimStatus();
            simstatus = getResult.Result;

            if (simstatus == null)
            {
                simstatusString = "unknown";
                //LogWriter.Report(LogEvent.SimStatus, "unknown");
            }
            else if (simstatus.IsInstalled)
            {
                simstatusString = "inserted";
                //LogWriter.Report(LogEvent.SimStatus, "inserted");
            }
            else
            {
                simstatusString = "none";
                //LogWriter.Report(LogEvent.SimStatus, "none");
            }

            if (simstatus == null)
            {
                Error = ErrorType.SimStatusReadFail;
                LogWriter.Report(LogEvent.SubSimStatus, simstatusString, isError: true);
                return false;
            }
            LogWriter.Log(string.Format("Get Sub Sim Status : {0} , Expect:{1}", simstatus.IsInstalled ? "installed" : "uninstalled", UpdateData.IsSubSimInsert ? "installed" : "uninstalled"));

            if (simstatus.IsInstalled != UpdateData.IsSubSimInsert)
            {
                Error = ErrorType.SimStatusMismatch;
                LogWriter.Report(LogEvent.SubSimStatus, simstatusString, isError: true);
                return false;
            }
            else
            {
                LogWriter.Report(LogEvent.SubSimStatus, simstatusString);
                if (simstatus.IsInstalled)
                {
                    //var iccidByteList = simstatus.ICCID.ToList();
                    //iccidByteList.RemoveAll(x => x == 0x00);
                    //var iccidBytes = iccidByteList.ToArray();

                    //var imsiByteList = simstatus.IMSI.ToList();
                    //imsiByteList.RemoveAll(x => x == 0x00);
                    //var imsiBytes = imsiByteList.ToArray();


                    //var ICCIDstring = Encoding.ASCII.GetString(iccidBytes).Trim();
                    //var IMSIstring = Encoding.ASCII.GetString(imsiBytes).Trim();
                    var ICCIDstring = simstatus.ICCID;
                    var IMSIstring = simstatus.IMSI;

                    //LogWriter.Report(LogEvent.SimICCID, ICCIDstring);
                    //LogWriter.Report(LogEvent.SimIMSI, IMSIstring);

                    LogWriter.Log(string.Format("Get Sim ICCID : {0} , Expect:{1}", ICCIDstring, UpdateData.SubSimICCID));
                    LogWriter.Log(string.Format("Get Sim IMSI : {0} , Expect:{1}", IMSIstring, UpdateData.SubSimIMSI));

                    if (ICCIDstring != UpdateData.SubSimICCID)
                    {
                        LogWriter.Log("Sim card ICCID not match");
                        Error = ErrorType.IccidMistach;
                        LogWriter.Report(LogEvent.SubSimICCID, ICCIDstring, isError: true);
                        return false;
                    }
                    else
                    {
                        LogWriter.Report(LogEvent.SubSimICCID, ICCIDstring);
                    }

                    if (IMSIstring != UpdateData.SubSimIMSI)
                    {
                        LogWriter.Log("Sim card IMSI not match");
                        Error = ErrorType.ImsiMistach;
                        LogWriter.Report(LogEvent.SubSimIMSI, IMSIstring, isError: true);
                        return false;
                    }
                    else
                    {
                        LogWriter.Report(LogEvent.SubSimIMSI, IMSIstring);
                    }
                }
                else
                {
                }
            }


            return true;
        }
    }
}