using System;
using System.Linq;
using System.ComponentModel;
using System.Drawing.Design;
using System.Runtime.CompilerServices;
using System.Management;
using AR;

namespace Project
{
    public class MyUITypeEditor : UITypeEditor
    {
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            using (var f = new System.Windows.Forms.Form
            {
                WindowState = System.Windows.Forms.FormWindowState.Normal,
                StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen,
                Size = new System.Drawing.Size(800, 400),
                MaximizeBox = false,
                MinimizeBox = false,
                Text = "Select Port",
                FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog
            })
            {
                var lst = new System.Windows.Forms.ListBox
                {
                    Font = new System.Drawing.Font("Consolas", 15, System.Drawing.FontStyle.Bold),
                    Dock = System.Windows.Forms.DockStyle.Fill,
                };
                lst.DoubleClick += (s1, e1) =>
                {
                    if (lst.SelectedItem != null) f.DialogResult = System.Windows.Forms.DialogResult.OK;
                };
                using (var searcher = new ManagementObjectSearcher("SELECT * FROM WIN32_SerialPort"))
                {
                    var portnames = System.IO.Ports.SerialPort.GetPortNames().OrderBy(t => t);
                    var ports = searcher.Get().Cast<ManagementBaseObject>().ToList();
                    foreach (var port in portnames)
                    {
                        var desc = "";
                        var portInfo = ports.Where(t => t["DeviceId"].ToString() == port).FirstOrDefault();
                        if (portInfo != null) desc = portInfo["Caption"].ToString();
                        lst.Items.Add(string.Format("{0} - {1}", port, desc));
                    }
                }
                f.Controls.Add(lst);
                if (f.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    var name = lst.SelectedItem.ToString().Split('-');
                    return name[0].Trim();
                }
                else
                {
                    return base.EditValue(context, provider, value);
                }
            }

        }
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
            return UITypeEditorEditStyle.Modal;
        }
    }

    public class CSetting : AR.Setting
    {
        #region "log"

        [Category("System Log"), DisplayName("Digital Input/Output"),
        Description("입/출력 장치의 상태 변화를 기록 합니다.")]
        public Boolean Log_IO { get; set; }
        [Category("System Log"), DisplayName("Network Alive Check(Ping)"),
        Description("서버와의 통신검사 로그를 기록 합니다")]
        public Boolean Log_Ping { get; set; }
        [Category("System Log"), DisplayName("S/M Step Change"),
        Description("상태머신의 변화 상태를 기록 합니다.")]
        public Boolean Log_StepChange { get; set; }
        [Category("System Log"), DisplayName("Socket Recv Message"),
        Description("서버 수신 메세지를 기록 합니다.")]
        public Boolean LOg_SocketRecv { get; set; }

        #endregion

        #region "Communication"

        [Category("Commnunication Setting"), DisplayName("XBee PortName"), Editor(typeof(MyUITypeEditor), typeof(UITypeEditor))]
        public string Port_XBE { get; set; }

        [Category("Commnunication Setting"), DisplayName("RFID PortName"), Editor(typeof(MyUITypeEditor), typeof(UITypeEditor))]
        public string Port_AGV { get; set; }

        [Category("Commnunication Setting"), DisplayName("Xbee ID"), Editor(typeof(MyUITypeEditor), typeof(UITypeEditor))]
        public byte XBE_ID { get; set; }


        [Category("Commnunication Setting"), DisplayName("BMS PortName"), Editor(typeof(MyUITypeEditor), typeof(UITypeEditor))]
        public string Port_BAT { get; set; }

        public int ChargerID { get; set; }

        public int Baud_AGV { get; set; }
        public int Baud_BAT { get; set; }
        //public int Baud_PLC { get; set; }
        public int Baud_XBE { get; set; }

        //public int QueryInterval_BAT { get; set; }


        #endregion

        #region "Debug"
        [Category("Developer Setting"), DisplayName("Listening Port"),
        Description("서버와의 통신을 위한 대기 포트(TCP) - 기본값 : 7979")]
        public int listenPort { get; set; }

        [Category("Developer Setting")]
        public Boolean UseDebugMode { get; set; }

        #endregion

        #region "Count Reset Setting"

        [Category("Count Reset Setting"), DisplayName("A/M Clear Enable"),
        Description("오전 초기화 여부\n작업수량을 초기화 하려면 True 로 설정하세요")]
        public Boolean datetime_Check_1 { get; set; }
        [Category("Count Reset Setting"), DisplayName("P/M Clear Enable"),
        Description("오후 초기화 여부\n작업수량을 초기화 하려면 True 로 설정하세요")]
        public Boolean datetime_Check_2 { get; set; }
        [Category("Count Reset Setting"), DisplayName("A/M Clear Time(HH:mm)"),
        Description("오전 초기화 시간(시:분)\n예) 09:00")]
        public string datetime_Reset_1 { get; set; }
        [Category("Count Reset Setting"), DisplayName("P/M Clear Time(HH:mm)"),
        Description("오후 초기화 시간(시:분)\n예) 19:00")]
        public string datetime_Reset_2 { get; set; }

        #endregion

        #region "general"




        [Category("General Setting"), DisplayName("Enable Popup Message"),
        Description("오류 발생시 별도의 메세지 창으로 표시합니다. 사용하지 않을 경우에는 우측 상단의 결과창의 메세지를 확인합니다.")]
        public Boolean ShowPopUpMessage { get; set; }
        [Category("General Setting"), DisplayName("Asset Number"),
       Description("자산번호(서버에 값 전송 시 사용됩니다)")]
        public string Asset { get; set; }

        [Category("General Setting"),
        Description("데이터 자동 소거 기간(일) 비활성=0")]
        public int AutoDeleteDay { get; set; }
        [Category("General Setting"),
       Description("데이터 자동 소거 조건(남은용량 %)")]
        public int AutoDeleteThreshold { get; set; }

        [Category("General Setting"), PasswordPropertyText(true)]
        public string Password_Setup { get; set; }

        [Category("General Setting"), Browsable(false)]
        public string Language { get; set; }

        [Category("General Setting"), DisplayName("Full Screen Window State"),
        Description("화면을 전체화면으로 사용 합니다.")]
        public Boolean FullScreen { get; set; }
        public bool DetectManualCharge { get; set; }
        public Boolean StartLog { get; set; }

        #endregion

        #region "TAGS"
        public int TAGPOT { get; set; }
        public int TAGNOT { get; set; }
        public int TAG_F2_F3 { get; set; }
        public int TAG_QC_F1 { get; set; }
        public int TAG_F1_F2 { get; set; }
        public int TAG_F3_F4 { get; set; }
        public int TAG_F4_F5 { get; set; }

        public int TAG_QA_QC { get; set; }
        public int TAGQAB { get; set; }
        public int TAGQAA { get; set; }


        public int TAGQCB { get; set; }
        public int TAGQCA { get; set; }
        public int TAGF1A { get; set; }
        public int TAGF2A { get; set; }
        public int TAGF3A { get; set; }
        public int TAGF4A { get; set; }
        public int TAGF5A { get; set; }

        public int TAGF1B { get; set; }
        public int TAGF2B { get; set; }
        public int TAGF3B { get; set; }
        public int TAGF4B { get; set; }
        public int TAGF5B { get; set; }
        #endregion

        #region "Charge"
        public int chargerpos { get; set; }
        public int ChargetWaitSec { get; set; }
        public int ChargeEmergencyLevel { get; set; }
        public int ChargeMaxLevel { get; set; }
        public int ChargeStartLevel { get; set; }
        public Boolean Enable_AutoCharge { get; set; }

        public int ChargeRetryTerm { get; set; }
        //public int ChargeIdleInterval { get; set; }
        public int ChargeMaxTime { get; set; }
        public int ChargeSearchTime { get; set; }

        #endregion

        #region "AGV"

        public bool AutoModeOffAndClearPosition { get; set; }
        public string musicfile { get; set; }

        /// <summary>
        /// FVI로 가능 방향이 Backward 인가?
        /// Forward 방향이라면 false 를 한다
        /// </summary>
        public Boolean AGV_Direction_FVI_Backward { get; set; }

        public Boolean Enable_Speak { get; set; }

        //public Boolean Disable_BMS { get; set; }
        //public Boolean Log_BMS_Tx { get; set; }
        //public Boolean Log_BMS_Rx { get; set; }
        //public double ChargeLimitLow { get; set; }
        //public double ChargeLimitHigh { get; set; }

        public string AGV_PANID { get; set; }
        public string AGV_CHANNEL { get; set; }
        public string AGV_ADDRESS { get; set; }

        public int SCK { get; set; }
        public int SSK { get; set; }
        public int STT { get; set; }
        public int SAD { get; set; }

        public byte ZSpeed { get; set; }
        public int SPD_L { get; set; }
        public int SPD_M { get; set; }
        public int SPD_H { get; set; }
        public int SPD_DRIVE { get; set; }

        public int SPD_S { get; set; }
        public int SPD_R { get; set; }


        public int PID_PH { get; set; }
        public int PID_PM { get; set; }
        public int PID_PL { get; set; }
        public int PID_IH { get; set; }
        public int PID_IM { get; set; }
        public int PID_IL { get; set; }
        public int PID_DH { get; set; }
        public int PID_DM { get; set; }
        public int PID_DL { get; set; }

        public int PID_PS { get; set; }
        public int PID_IS { get; set; }
        public int PID_DS { get; set; }

        public double WheelSpeedCharge { get; set; }
        public byte HomePositionValue { get; set; }
        public byte HomeKitNo { get; set; }
        public Single interval_xbe { get; set; }
        public int interval_bms { get; set; }
        public int doorSoundTerm { get; set; }
        public int musicvol { get; set; }

        public bool Enable_Music { get; set; }
        #endregion

        [Category("Report"),
      Description("상태기록시 장비 식별코드(4자리)"),
      DisplayName("M/C ID")]
        public string MCID { get; set; }

        [Category("Report"),
        Description("작업 기록을 장비기술(EE)  Database 에 기록 합니다. 원격으로 장비 현황을 모니터링 할 수 있습니다"),
        DisplayName("SAVE EE-DB")]
        public Boolean Save_EEDatabase { get; set; }
        [Category("Report"), Description("상태값을 전송하는 간격(초)")]
        public int StatusInterval { get; set; }


        [Category("AutoReboot"),
            DisplayName("자동재부팅시간"),
            Description("기본값 14:00:00~14:05:00 , 재부팅은 장비가 대기(IDLE)일 때에만 동작하며 지정 시간 범위를 벗어나면 동작하지 않습니다")]
        public String AutoRebootTimeStart { get; set; }
        [Category("AutoReboot")]
        public string AUtoRebootLastTime { get; set; }


        public bool SetAutoModeOn { get; set; }
        public override void AfterLoad()
        {
            if (StatusInterval < 10) StatusInterval = 300; //5분간격

            if (SAD == 0) SAD = 999;
            if (TAGF1A == 0)
            {
                TAGNOT = 9000;

                TAGQAB = 9200;
                TAGQCB = 9300;
                TAGF1B = 9400;
                TAGF2B = 9500;
                TAGF3B = 9600;
                TAGF4B = 9700;
                TAGF5B = 9800;

                TAGQAA = 9201;
                TAGQCA = 9301;
                TAGF1A = 9401;
                TAGF2A = 9501;
                TAGF3A = 9601;
                TAGF4A = 9701;
                TAGF5A = 9801;

                TAGPOT = 9900;

                TAG_QA_QC = 9250;
                TAG_QC_F1 = 9350;
                TAG_F1_F2 = 9450;
                TAG_F2_F3 = 9550;
                TAG_F3_F4 = 9650;
                TAG_F4_F5 = 9750;
            }
            
            if(TAG_F4_F5 == 0)
            {
                TAG_F4_F5 = 9750;
                TAGF5B = 9800;
                TAGF5A = 9801;
            }

            if (SCK == 0) SCK = 10;
            if (SSK == 0) SSK = 10;
            if (STT == 0) STT = 30;
            if (ChargerID == 0) ChargerID = 203;
            if (ChargerID < 200) ChargerID += 200;

            //자동충전요건
            if (ChargetWaitSec == 0) ChargetWaitSec = 3;
            if (ChargeStartLevel == 0) ChargeStartLevel = 85;
            if (ChargeMaxLevel == 0) ChargeMaxLevel = 85;
            if (ChargeEmergencyLevel == 0) ChargeEmergencyLevel = 30;
            if (interval_bms == 0) interval_bms = 10;

            //충전은 10분간격으로 재시도 한다
            if (ChargeRetryTerm == 0) ChargeRetryTerm = 600;
            if (doorSoundTerm == 0) doorSoundTerm = 15; //기본 15초
            if (ChargeSearchTime == 0) ChargeSearchTime = 25;
            //최대 충전진행 시간(기본 1시간)
            if (ChargeMaxTime == 0) ChargeMaxTime = 3600;
           // if (interval_iostate == 0 || interval_iostate == 255) interval_iostate = 100;
            if (ZSpeed == 0) ZSpeed = 20;
            if (interval_xbe == 0) interval_xbe = 5.0f;
            if (HomePositionValue == 0) HomePositionValue = 4;
            if (HomeKitNo == 0) HomeKitNo = 2;
            if (datetime_Reset_1 == "") datetime_Reset_1 = "00:00";
            if (datetime_Reset_2 == "") datetime_Reset_2 = "00:00";

            if (SPD_H == 0)
            {
                SPD_DRIVE = 200;
                SPD_H = 110;
                SPD_M = 70;
                SPD_L = 30;
                SPD_S = 61;
                SPD_R = 70;
            }

            if (PID_PH == 0)
            {
                PID_PH = 180; PID_PM = 240; PID_PL = 260;
                PID_IH = 610; PID_IM = 640; PID_IL = 660;
                PID_DH = 110; PID_DM = 140; PID_DL = 160;
                PID_PS = 200; PID_IS = 620; PID_DS = 120;
            }

            if (WheelSpeedCharge == 0) WheelSpeedCharge = 10;

            if (AutoDeleteThreshold == 0) AutoDeleteThreshold = 20;
            if (Asset == "") Asset = "DEV_SPLIT";
            if (listenPort == 0) listenPort = 7979;
            if (Port_XBE == "") Port_XBE = "COM8";

            if (Language.isEmpty()) Language = "Kor";
            if (Password_Setup.isEmpty()) Password_Setup = "0000";
            if (musicfile.isEmpty()) musicfile = UTIL.CurrentPath + "music.mp3";
            if (musicvol == 0) musicvol = 50;


            if (string.IsNullOrEmpty(Port_AGV)) Port_AGV = "COM1";
           // if (string.IsNullOrEmpty(Port_PLC)) Port_PLC = "COM2";
            if (string.IsNullOrEmpty(Port_XBE)) Port_XBE = "COM4";
            if (string.IsNullOrEmpty(Port_BAT)) Port_BAT = "COM7";

            if (Baud_AGV == 0) Baud_AGV = 57600;
            //if (Baud_PLC == 0) Baud_PLC = 19200;
            if (Baud_XBE == 0) Baud_XBE = 9600;
            if (Baud_BAT == 0) Baud_BAT = 9600;


        }
        public override void AfterSave()
        {
            //throw new NotImplementedException();
        }

        public void CopyTo(CSetting dest)
        {
            //이곳의 모든 쓰기가능한 속성값을 대상에 써준다.
            Type thClass = this.GetType();
            foreach (var method in thClass.GetMethods())
            {
                //var parameters = method.GetParameters();
                if (!method.Name.StartsWith("get_")) continue;

                string keyname = method.Name.Substring(4);
                string methodName = method.Name;

                object odata = GetType().GetMethod(methodName).Invoke(this, null);
                var wMethod = dest.GetType().GetMethod(Convert.ToString("set_") + keyname);
                if (wMethod != null) wMethod.Invoke(dest, new object[] { odata });
            }
        }
    }


    public class CounterSetting : AR.Setting, INotifyPropertyChanged
    {
        public DateTime CountReset { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private int countUp1 = 0;
        private int countUp2 = 0;
        private int countUp3 = 0;
        private int countUp4 = 0;
        // private int countUp5 = 0;
        private int countchgaerr = 0;
        private int countchga = 0;
        private int countchgm = 0;
        //private int countdn = 0;
        private int countqa = 0;
        private int countqc = 0;

        //메인카운터
        public int CountUp1
        {
            get { return countUp1; }
            set { if (value != countUp1) { countUp1 = value; NotifyPropertyChanged(); } }
        }
        public int CountUp2
        {
            get { return countUp2; }
            set { if (value != countUp2) { countUp2 = value; NotifyPropertyChanged(); } }
        }
        public int CountUp3
        {
            get { return countUp3; }
            set { if (value != countUp3) { countUp3 = value; NotifyPropertyChanged(); } }
        }
        public int CountUp4
        {
            get { return countUp4; }
            set { if (value != countUp4) { countUp4 = value; NotifyPropertyChanged(); } }
        }
        //public int CountUp5
        //{
        //    get { return countUp5; }
        //    set { if (value != countUp5) { countUp5 = value; NotifyPropertyChanged(); } }
        //}

        /// <summary>
        /// 상차수량(FVI 1+2+3+4)
        /// </summary>
        public int CountUp
        {
            get
            {
                return CountUp1 + CountUp2 + CountUp3 + CountUp4;// + CountUp5;
            }
        }

        public int CountChargeE
        {
            get { return this.countchgaerr; }
            set { if (value != countchgaerr) { countchgaerr = value; NotifyPropertyChanged(); } }
        }
        public int CountChargeA
        {
            get { return this.countchga; }
            set { if (value != countchga) { countchga = value; NotifyPropertyChanged(); } }
        }
        public int CountChargeM
        {
            get { return this.countchgm; }
            set { if (value != countchgm) { countchgm = value; NotifyPropertyChanged(); } }
        }

        /// <summary>
        /// 하차수량(QC+QA)
        /// </summary>
        public int CountDn
        {
            get { return this.countqa + this.countqc; }
            //set { if (value != countdn) { countdn = value; NotifyPropertyChanged(); } }
        }
        public int CountQA
        {
            get { return this.countqa; }
            set { if (value != countqa) { countqa = value; NotifyPropertyChanged(); } }
        }
        public int CountQC
        {
            get { return this.countqc; }
            set { if (value != countqc) { countqc = value; NotifyPropertyChanged(); } }
        }
        public void CountClear()
        {
            CountUp1 = 0;
            CountUp2 = 0;
            CountUp3 = 0;
            CountUp4 = 0;
            // CountUp5 = 0;
            CountQC = 0;
            CountQA = 0;
            //CountQa2 = 0;
            CountReset = DateTime.Now;
            PUB.log.Add("Count Clear");
            this.Save();
        }

        public CounterSetting()
        {
            this.filename = AR.UTIL.CurrentPath + "counter.xml";
        }
        public override void AfterLoad()
        {
            if (CountReset == null) CountReset = DateTime.Parse("1982-11-23");
        }
        public override void AfterSave()
        {
            //throw new NotImplementedException();
        }
    }

}
