using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Net;
using System.IO;

namespace FLY.Simulation.Blowing
{
    public class HMI: IPlcLink
    {
        const int ADDR_M_HasElectricCurrent = 0;//bit 三相电 电流
        const int ADDR_M_HasFan = 1;//bit 风机启动
        
        const int ADDR_D_ChannelCnt = 0;
        const int ADDR_D_HeatUpdate = 1;
        const int ADDR_D_CurrUpdate = 2;
        
        const UInt16 ADDR_D_Heats = 100;
        const UInt16 ADDR_D_Currs = 300;

        public UInt16 HeatUpdate { get; set; }

        public UInt16 CurrUpdate { get; set; }


        /// <summary>
        /// 当前电流 有没？
        /// </summary>
        public bool HasElectricCurrent { get; set; }

        /// <summary>
        /// 风机是否启动？
        /// </summary>
        public bool HasFan { get; set; } = true;
        public string PlcAddr { get; set; } = "127.0.0.1";

        UInt16 heatupdate = 1;
        UInt16 currupdate = 1;
        UInt16 heatupdate_last = 1;
        UInt16[] heats;
        public Blowing.AirRing mAirRing;
        FLY.ModbusModule.ClientTCP mbclient;



        public HMI() 
        {

            if (!Load())
                Save();

            heats = new UInt16[100];

            Array.Clear(heats, 0, 100);



            heatupdate = 1;
            heatupdate_last = 1;
            currupdate = 1;



        }
        public void Init(Blowing.AirRing mAirRing) 
        {
            this.mAirRing = mAirRing;

            mbclient = new FLY.ModbusModule.ClientTCP(IPAddress.Parse(PlcAddr));

            mbclient.PropertyChanged += new PropertyChangedEventHandler(mbclient_PropertyChanged);
            //每1秒读取一次
            FObjBase.PollModule.Current.Poll_Config(FObjBase.PollModule.POLL_CONFIG.ADD,
                new FObjBase.PollModule.PollHandler(OnPoll), TimeSpan.FromMilliseconds(200));
        }
        void mbclient_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsConnected") 
            {
                if (mbclient.IsConnected)
                {
                    step = 0;
                }
                else 
                {
                    step = -1;
                }

            }
        }
        int step = -1;
        void OnPoll() 
        {
            switch (step)
            {
                case 0:
                    mbclient.Do_03(ADDR_D_HeatUpdate, 1, delegate(UInt16[] datas, object AsyncState)
                    {
                        HeatUpdate = datas[0];
                        step = 2;
                    }, null);
                    step = 1;
                    break;
                case 2:
                    mbclient.Do_03(ADDR_D_Heats, 100, delegate(UInt16[] datas, object AsyncState)
                    {
                        Array.Copy(datas, heats, 100);                        
                        step = 4;
                    }, null);
                    step = 3;
                    break;
                case 4:
                    OnPoll_send();
                    step = 0;
                    break;
            }
        }
        
        void SendHeats() 
        {
            mbclient.Do_10(ADDR_D_Currs,heats); 
        }
        void SendUpdate() 
        {
            mbclient.Do_10(ADDR_D_CurrUpdate, new ushort[]{ CurrUpdate});
        }
        void SendStatue() 
        {
            mbclient.Do_0F(ADDR_M_HasElectricCurrent, new bool[] { HasElectricCurrent, HasFan });
        }
        void OnPoll_send() 
        {
            if (heatupdate_last != HeatUpdate) 
            {
                heatupdate_last = HeatUpdate;

                for (int i = 0; i < mAirRing.ChannelCnt; i++) 
                {
                    mAirRing.Heats[i] = heats[i];
                }
                mAirRing.HeatApply();
                SendHeats();

                HasElectricCurrent = mAirRing.HasElectricCurrent;
                CurrUpdate++;
                SendUpdate();

            }
            SendStatue();
        }
        string filePath = "airRingPlc.json";
        bool Load()
        {
            return HmiJsonDb.Load(filePath, this);
        }
        public bool Save()
        {
            return HmiJsonDb.Save(filePath, this);
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

    public class HmiJsonDb
    {
        public string PlcAddr = "127.0.0.1";
        public static bool Save(string filePath, HMI plcLink)
        {
            try
            {
                HmiJsonDb jsondb = new HmiJsonDb()
                {
                    PlcAddr = plcLink.PlcAddr
                };
                string json = Newtonsoft.Json.JsonConvert.SerializeObject(jsondb, Newtonsoft.Json.Formatting.Indented);
                File.WriteAllText(filePath, json);
                return true;
            }
            catch
            {
                return false;
            }
        }
        public static bool Load(string filePath, HMI plcLink)
        {
            try
            {
                if (!File.Exists(filePath))
                    return false;
                string json = File.ReadAllText(filePath);
                var jsonDb = Newtonsoft.Json.JsonConvert.DeserializeObject<HmiJsonDb>(json);
                plcLink.PlcAddr = jsonDb.PlcAddr;
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}
