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

namespace FLY.Simulation.Coating
{
    public class HMI : INotifyPropertyChanged
    {
        const UInt16 ADDR_D_PumpSet=0;//泵速设置 & 泵速显示, float
  
        const UInt16 ADDR_D_LeftSet=10;//uint16  65535-> 6553.5
        const UInt16 ADDR_D_Left=12;

        const UInt16 ADDR_D_RightSet=14;//uint16  65535-> 6553.5
        const UInt16 ADDR_D_Right=16;


        const UInt16 ADDR_D_FilmVelocity=6;//float
        const UInt16 ADDR_C_STATE = 0;//涂布状态 bit 0

        const UInt16 ADDR_C_OK = 2;//设置 0->1 设置

        CoatingCtrl mCoatingCtrl;

        FLY.ModbusModule.ServerTCP mbServer;
        FLY.ModbusModule.PLCRegister mPLCRegister;

        Dictionary<UInt16, string> Addrs_reg = new Dictionary<ushort, string>();
        Dictionary<UInt16, string> Addrs_coil = new Dictionary<ushort, string>();


        public double PumpSet 
        {
            get {
                float p = mPLCRegister.GetFloat(ADDR_D_PumpSet);
                return p;
            }
            set {
                if (PumpSet != value)
                {
                    mPLCRegister.SetFloat(ADDR_D_PumpSet, (float)value);
                    NotifyPropertyChanged(nameof(PumpSet));
                }
            }
        }
        public double LeftSet
        {
            get
            {
                UInt16 p = mPLCRegister.GetUInt16(ADDR_D_LeftSet);
                return p / 10.0;
            }
            set
            {
                if (LeftSet != value)
                {
                    mPLCRegister.SetUInt16(ADDR_D_LeftSet, (UInt16)(value * 10));
                    NotifyPropertyChanged(nameof(LeftSet));
                }
            }
        }
        public double Left
        {
            get
            {
                UInt16 p = mPLCRegister.GetUInt16(ADDR_D_Left);
                return p / 10.0;
            }
            set
            {
                if (Left != value)
                {
                    mPLCRegister.SetUInt16(ADDR_D_Left, (UInt16)(value * 10));
                    NotifyPropertyChanged(nameof(Left));
                }
            }
        }
        public double RightSet
        {
            get
            {
                UInt16 p = mPLCRegister.GetUInt16(ADDR_D_RightSet);
                return p / 10.0;
            }
            set
            {
                if (RightSet != value)
                {
                    mPLCRegister.SetUInt16(ADDR_D_RightSet, (UInt16)(value * 10));
                    NotifyPropertyChanged(nameof(RightSet));
                }
            }
        }
        public double Right
        {
            get
            {
                UInt16 p = mPLCRegister.GetUInt16(ADDR_D_Right);
                return p / 10.0;
            }
            set
            {
                if (Right != value)
                {
                    mPLCRegister.SetUInt16(ADDR_D_Right, (UInt16)(value * 10));
                    NotifyPropertyChanged(nameof(Right));
                }
            }
        }


        public double FilmVelocity
        {
            get
            {
                float p = mPLCRegister.GetFloat(ADDR_D_FilmVelocity);
                return p;
            }
            set
            {
                if (FilmVelocity != value)
                {
                    mPLCRegister.SetFloat(ADDR_D_FilmVelocity, (float)value );
                    NotifyPropertyChanged(nameof(FilmVelocity));
                }
            }
        }


        public bool State
        {
            get
            {
                return mPLCRegister.GetBool(ADDR_C_STATE);
            }
            set
            {
                if (State != value)
                {
                    mPLCRegister.SetBool(ADDR_C_STATE, value);
                    NotifyPropertyChanged(nameof(State));
                }
            }
        }

        public bool OK
        {
            get
            {
                return mPLCRegister.GetBool(ADDR_C_OK);
            }
            set
            {
                if (OK != value)
                {
                    mPLCRegister.SetBool(ADDR_C_OK, value);
                    NotifyPropertyChanged(nameof(OK));
                }
            }
        }
        private bool ok_last = false;
        public HMI(Coating coating, CoatingCtrl cc, int port)
        {
            mCoatingCtrl = cc;
           
            mPLCRegister = new ModbusModule.PLCRegister(200, 200);
            mbServer = new FLY.ModbusModule.ServerTCP(mPLCRegister, (UInt16)port);

            mPLCRegister.RegChanged += new ModbusModule.PLCRegister.RegChangedEventHandler(plcregister_RegChanged);

            ok_last = OK;

            Addrs_reg.Add(ADDR_D_PumpSet, "PumpSet");
            Addrs_reg.Add(ADDR_D_LeftSet, "LeftSet");
            Addrs_reg.Add(ADDR_D_Left, "Left");
            Addrs_reg.Add(ADDR_D_RightSet, "RightSet");
            Addrs_reg.Add(ADDR_D_Right, "Right");
            Addrs_reg.Add(ADDR_D_FilmVelocity, "FilmVelocity");
            Addrs_coil.Add(ADDR_C_OK, "OK");
            Addrs_coil.Add(ADDR_C_STATE, "State");


            Misc.BindingOperations.SetBinding(cc.NowCtrl, "Pump", this, "PumpSet", Misc.BindingOperations.BindingMode.TwoWay);
            Misc.BindingOperations.SetBinding(cc.NowCtrl, "LeftDis", this, "Left");
            Misc.BindingOperations.SetBinding(cc.NowCtrl, "RightDis", this, "Right");
            Misc.BindingOperations.SetBinding(coating, "FilmVelocity", this, "FilmVelocity");
            Misc.BindingOperations.SetBinding(coating, "DeviceState", this, "State");


            LeftSet = Left;
            RightSet = Right;
            this.PropertyChanged += new PropertyChangedEventHandler(HMI_PropertyChanged);

            
        }

        void HMI_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {

            if (e.PropertyName == "OK")
            {
                if (ok_last != OK)
                {
                    ok_last = OK;

                    if (OK == true)
                    {
                        mCoatingCtrl.SetCoatingCtrl(PumpSet, LeftSet, RightSet);
                    }
                }
            }
        }

        void plcregister_RegChanged(object sender, ModbusModule.PLCRegister.RegChangedEventArgs e)
        {
            if (e.RegType == ModbusModule.PLCRegister.RegChangedEventArgs.REG_TYPE.REG)
            {
                foreach (UInt16 key in Addrs_reg.Keys)
                {
                    if (e.IsCover(key))
                    {
                        NotifyPropertyChanged(Addrs_reg[key]);
                    }
                }
            }
            else 
            {
                foreach (UInt16 key in Addrs_coil.Keys)
                {
                    if (e.IsCover(key))
                    {
                        NotifyPropertyChanged(Addrs_coil[key]);
                    }
                }
            }
        }

        protected void NotifyPropertyChanged(string propertyname)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyname));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}
