using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LFP_Manager.DataStructure
{
    internal class CsAlarmDefine
    {
        //0x0001：Pack OV 
        //0x0002：Cell OV 
        //0x0004：Pack UV 
        //0x0008：Cell UV 
        //0x0010：Charge OC
        //0x0020：Discharge OC
        //0x0040: 环境温度异常
        //0x0080: MOS温度高
        //0x0100：Charge OT
        //0x0200：Discharge OT
        //0x0400：Charge UT
        //0x0800：Discharge UT
        //0x1000：Low capacity
        //0x2000: 浮充停止/Float Stoped
        //0x4000: 

        public enum eGuiWarningBit
        {
            PACK_OV = 0,
            CELL_OV = 1,
            PACK_UV = 2,
            CELL_UV = 3,
            CHG_OC = 4,
            DCH_OC = 5,
            AMB_OT = 6,
            MOS_OT = 7,
            CHG_OT = 8,
            DCH_OT = 9,
            CHG_UT = 10,
            DCH_UT = 11,
            LOW_SOC = 12,
            DIFF_VOLT = 13,
            CB_OFF = 14,
        }
        public enum eGuiProtectBit
        {
            PACK_OV = 0,
            CELL_OV = 1,
            PACK_UV = 2,
            CELL_UV = 3,
            CHG_OC = 4,
            DCH_OC = 5,
            AMB_OT = 6,
            MOS_OT = 7,
            CHG_OT = 8,
            DCH_OT = 9,
            CHG_UT = 10,
            DCH_UT = 11,
            LOW_SOC = 12,
            SC = 13,
        }
        public enum eDevWarningBit
        {
            CELL_OV = 0,
            CELL_UV = 1,
            PACK_OV = 2,
            PACK_UV = 3,
            CHG_OC = 4,
            DCH_OC = 5,
            AMB_OT = 6,
            AMB_UT = 7,
            CHG_OT = 8,
            CHG_UT = 9,
            DCH_OT = 10,
            DCH_UT = 11,
            LOW_SOC = 12,
            DIFF_VOLT = 13,
            CB_OFF = 14,
        }
        public enum eDevProtectBit
        {
            CELL_OV = 0,
            PACK_OV = 1,
            CELL_UV = 2,
            PACK_UV = 3,
            CHG_OC1 = 4,
            CHG_OC2 = 5,
            DCH_OC1 = 6,
            DCH_OC2 = 7,
            SC_CB = 8,
            CHG_OT = 9,
            CHG_UT = 10,
            DCH_OT = 11,
            DCH_UT = 12,
        }

        private static bool HasBit(int value, int bitIndex) => (value & (1 << bitIndex)) != 0;
        private static void SetBit(ref int value, int bitIndex) => value |= (1 << bitIndex);
        private static void SetIf(int src, int srcBit, ref int dst, int dstBit)
        {
            if (HasBit(src, srcBit)) SetBit(ref dst, dstBit);
        }
        private static void SetIfAny(int src, int[] srcBits, ref int dst, int dstBit)
        {
            foreach (var b in srcBits)
            {
                if (HasBit(src, b)) { SetBit(ref dst, dstBit); break; }
            }
        }

        /// <summary>
        /// Device 경고 비트(eDevWarningBit) -> GUI 경고 비트(eGuiWarningBit)
        /// AMB_UT는 GUI 경고에 대응 비트가 없어 미표시.
        /// 새로 추가된 DIFF_VOLT, CB_OFF 매핑 포함.
        /// </summary>
        public static int DevWarningToGui(int devWarning)
        {
            int gui = 0;

            SetIf(devWarning, (int)eDevWarningBit.PACK_OV, ref gui, (int)eGuiWarningBit.PACK_OV);
            SetIf(devWarning, (int)eDevWarningBit.CELL_OV, ref gui, (int)eGuiWarningBit.CELL_OV);
            SetIf(devWarning, (int)eDevWarningBit.PACK_UV, ref gui, (int)eGuiWarningBit.PACK_UV);
            SetIf(devWarning, (int)eDevWarningBit.CELL_UV, ref gui, (int)eGuiWarningBit.CELL_UV);

            SetIf(devWarning, (int)eDevWarningBit.CHG_OC, ref gui, (int)eGuiWarningBit.CHG_OC);
            SetIf(devWarning, (int)eDevWarningBit.DCH_OC, ref gui, (int)eGuiWarningBit.DCH_OC);

            SetIf(devWarning, (int)eDevWarningBit.AMB_OT, ref gui, (int)eGuiWarningBit.AMB_OT);
            //SetIf(devWarning, (int)eDevWarningBit.MOS_OT, ref gui, (int)eGuiWarningBit.MOS_OT);

            SetIf(devWarning, (int)eDevWarningBit.CHG_OT, ref gui, (int)eGuiWarningBit.CHG_OT);
            SetIf(devWarning, (int)eDevWarningBit.DCH_OT, ref gui, (int)eGuiWarningBit.DCH_OT);
            SetIf(devWarning, (int)eDevWarningBit.CHG_UT, ref gui, (int)eGuiWarningBit.CHG_UT);
            SetIf(devWarning, (int)eDevWarningBit.DCH_UT, ref gui, (int)eGuiWarningBit.DCH_UT);

            SetIf(devWarning, (int)eDevWarningBit.LOW_SOC, ref gui, (int)eGuiWarningBit.LOW_SOC);
            SetIf(devWarning, (int)eDevWarningBit.DIFF_VOLT, ref gui, (int)eGuiWarningBit.DIFF_VOLT);
            SetIf(devWarning, (int)eDevWarningBit.CB_OFF, ref gui, (int)eGuiWarningBit.CB_OFF);

            // AMB_UT는 GUI에 해당 없음 → 미표시
            return gui;
        }

        /// <summary>
        /// Device 보호 비트(eDevProtectBit) -> GUI 보호 비트(eGuiProtectBit)
        /// CHG_OC1/2 → CHG_OC 집계, DCH_OC1/2 → DCH_OC 집계
        /// SC_CB(단락/차단기 트립) → SC(신규 GUI 비트) 매핑.
        /// </summary>
        public static int DevProtectToGui(int devProtect)
        {
            int gui = 0;

            SetIf(devProtect, (int)eDevProtectBit.PACK_OV, ref gui, (int)eGuiProtectBit.PACK_OV);
            SetIf(devProtect, (int)eDevProtectBit.CELL_OV, ref gui, (int)eGuiProtectBit.CELL_OV);
            SetIf(devProtect, (int)eDevProtectBit.PACK_UV, ref gui, (int)eGuiProtectBit.PACK_UV);
            SetIf(devProtect, (int)eDevProtectBit.CELL_UV, ref gui, (int)eGuiProtectBit.CELL_UV);

            SetIfAny(devProtect, new[] { (int)eDevProtectBit.CHG_OC1, (int)eDevProtectBit.CHG_OC2 },
                     ref gui, (int)eGuiProtectBit.CHG_OC);
            SetIfAny(devProtect, new[] { (int)eDevProtectBit.DCH_OC1, (int)eDevProtectBit.DCH_OC2 },
                     ref gui, (int)eGuiProtectBit.DCH_OC);

            // 단락/차단기 트립 → SC
            SetIf(devProtect, (int)eDevProtectBit.SC_CB, ref gui, (int)eGuiProtectBit.SC);

            SetIf(devProtect, (int)eDevProtectBit.CHG_OT, ref gui, (int)eGuiProtectBit.CHG_OT);
            SetIf(devProtect, (int)eDevProtectBit.CHG_UT, ref gui, (int)eGuiProtectBit.CHG_UT);
            SetIf(devProtect, (int)eDevProtectBit.DCH_OT, ref gui, (int)eGuiProtectBit.DCH_OT);
            SetIf(devProtect, (int)eDevProtectBit.DCH_UT, ref gui, (int)eGuiProtectBit.DCH_UT);

            // AMB_OT, MOS_OT, LOW_SOC 보호 카테고리는 DevProtectBit에 정의되지 않아 미표시
            return gui;
        }
    }
}
