using FLY.Thick.Base.Common;
using FLY.Thick.Base.IService;
using FlyADBase;
using FObjBase;
using FObjBase.Reflect;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AREA_ERR = FLY.Thick.Base.Common.AREA_ERR;
using AREA_STATUS = FLY.Thick.Base.Common.AREA_STATUS;
using MOTORTYPE = FLY.Thick.Base.Common.MOTORTYPE;

namespace FLY.Thick.Base.Server
{
    public class FlyAdService : IFlyADService
    {
        #region 延时推送 MARKNO
        const int MARKNO_PUSH_ACCESS = 2;
        #endregion

        public bool HasCRC {
            get {
                return flyad.HasCRC;
            }
            set
            {
                flyad.HasCRC = value;
            }
        }
        public string Addr
        {
            get
            {
                return flyad.Addr;
            }
            set
            {
                if (flyad.Addr != value) {
                    flyad.Connect(value);
                }
            }
        }
        public UInt16 PosOfGrid
        {
            get
            {
                return flyad.PosOfGrid;
            }
            set
            {
                flyad.PosOfGrid = value;
            }
        }
        public int PosLen
        {
            get
            {
                return flyad.PosLen;
            }
            set
            {
                flyad.PosLen = value;
            }
        }
        public MOTORTYPE MotorType
        {
            get
            {
                return (MOTORTYPE)flyad.MotorType;
            }
            set
            {
                flyad.MotorType = (FlyADBase.MOTORTYPE)value;
            }
        }
        public UInt16 Ratio01
        {
            get
            {
                return flyad.Ratio01;
            }
            set
            {
                flyad.Ratio01 = value;
            }
        }
        public UInt16 Ratio02
        {
            get
            {
                return flyad.Ratio02;
            }
            set
            {
                flyad.Ratio02 = value;
            }
        }
        public Int16 PosOffset
        {
            get
            {
                return flyad.PosOffset;
            }
            set
            {
                flyad.PosOffset = value;
            }
        }
        public UInt32 JogVelocity
        {
            get
            {
                return flyad.JogVelocity;
            }
            set
            {
                flyad.JogVelocity = value;
            }
        }
        public int GridSmooth
        {
            get
            {
                return flyad.GridSmooth;
            }
            set
            {
                flyad.GridSmooth = value;
            }
        }

        public int ADLag 
        {
            get { return flyad.ADLag; }
            set {
                flyad.ADLag = value;
            }
        }
        public bool HasPosMaxMin
        {
            get { return flyad.HasPosMaxMin; }
            set
            {
                flyad.HasPosMaxMin = value;
            }
        }
        public int PosMin
        {
            get { return flyad.PosMin; }
            set
            {
                flyad.PosMin = value;
            }
        }
        public int PosMax
        {
            get { return flyad.PosMax; }
            set
            {
                flyad.PosMax = value;
            }
        }

        public int Verson 
        {
            get { return flyad.Version; }
        }
        public int HardwareVersion {
            get { return flyad.HardwareVersion; }
            set {
                flyad.HardwareVersion = value;
            }
        }
        IFlyADClientAdv flyad;
        AD2ThkHandler ad2thk;
        public FlyAdService()
        {

        }
        public void Init(IFlyADClientAdv flyad, AD2ThkHandler func_Ad2Thk) 
        {

            ad2thk = func_Ad2Thk;
            this.flyad = flyad;

            this.flyad.PropertyChanged += Flyad_PropertyChanged;
        }
        private void Flyad_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            var type = typeof(FlyAdService);
            if (type.GetProperty(e.PropertyName) != null) {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(e.PropertyName));
            }
        }

        /// <summary>
        /// 获取序列码
        /// </summary>
        /// <param name="asyncDelegate"></param>
        /// <param name="asyncContext"></param>
        [Call(typeof(AccessInfo))]
        public void GetAccessInfo(AsyncCBHandler asyncDelegate, object asyncContext)
        {
            AccessInfo ainfo = new AccessInfo()
            {
                status = (AREA_STATUS)flyad.AreaStatus,
                ret = (AREA_ERR)flyad.AreaRet,
                surplus = flyad.Surplus,
                code = flyad.Code,
                access = flyad.Access
            };
            asyncDelegate(asyncContext, ainfo);
        }

        class AsyncDelegateObj
        {
            public AsyncCBHandler asyncDelegate;
            public object asyncContext;
        }
        List<AsyncDelegateObj> setAccessRetList = new List<AsyncDelegateObj>();

        PropertyChangedEventHandler mFlyAD_PropertyChangedHandler = null;

        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// 设置授权码
        /// </summary>
        /// <param name="access"></param>
        /// <param name="asyncDelegate"></param>
        /// <param name="asyncContext"></param>
        [Call(typeof(AccessInfo))]
        public void SetAccess(byte[] access, AsyncCBHandler asyncDelegate, object asyncContext)
        {
            flyad.SetAccess(access);
            setAccessRetList.Add(new AsyncDelegateObj() { asyncDelegate = asyncDelegate, asyncContext = asyncContext });

            if (mFlyAD_PropertyChangedHandler == null)
            {
                mFlyAD_PropertyChangedHandler = new PropertyChangedEventHandler(delegate (object sender, PropertyChangedEventArgs e)
                {
                    if ((e.PropertyName == nameof(flyad.AreaStatus)) ||
                        (e.PropertyName == nameof(flyad.Code)) ||
                        (e.PropertyName == nameof(flyad.Surplus)) ||
                        (e.PropertyName == nameof(flyad.Access)) ||
                        (e.PropertyName == nameof(flyad.AreaRet)))
                    {
                        FObjBase.PollModule.Current.Poll_JustOnce(
                                new PollModule.PollHandler(delegate ()
                                {
                                    flyad.PropertyChanged -= mFlyAD_PropertyChangedHandler;
                                    AccessInfo ainfo = new AccessInfo()
                                    {
                                        status = (AREA_STATUS)flyad.AreaStatus,
                                        ret = (AREA_ERR)flyad.AreaRet,
                                        surplus = flyad.Surplus,
                                        code = flyad.Code,
                                        access = flyad.Access
                                    };
                                    for (int i = 0; i < setAccessRetList.Count(); i++)
                                    {
                                        setAccessRetList[i].asyncDelegate(setAccessRetList[i].asyncContext, ainfo);
                                    }
                                    setAccessRetList.Clear();
                                }), this, MARKNO_PUSH_ACCESS);
                    };
                });
            }
            flyad.PropertyChanged += mFlyAD_PropertyChangedHandler;
        }

        /// <summary>
        /// 获取grid
        /// </summary>
        /// <param name="direction"></param>
        /// <param name="asyncDelegate"></param>
        /// <param name="asyncContext"></param>
        [Call(typeof(GridInfo))]
        public void GetGrid(Misc.DIRECTION direction, AsyncCBHandler asyncDelegate, object asyncContext) 
        {
            flyad.GetGrid(direction, out int[] dat);
            double[] thks = null;
            if (dat != null)
            {
                thks = dat.Select(ad => ad2thk(ad)).ToArray();
            }

            GridInfo p = new GridInfo()
            {
                direction = direction,
                data = dat,
                thick = thks
            };
            asyncDelegate(asyncContext, p);
        }
    }
}
