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

using System.ComponentModel;
using FObjBase;
using FLY.Thick.Base.OBJ_INTERFACE;
using FLY.Thick.Base.Common;
using FLY.Thick.Base.IService;

namespace FLY.Thick.Base.Server.OBJProxy
{
    public class FlyAD_OBJProxy: FObj
    {
        #region 延时推送 MARKNO
        const int MARKNO_PUSH_PARAMS = 1;
        const int MARKNO_PUSH_ACCESS = 2;
        #endregion

        FlyADBase.FlyAD7 mFlyAD;

        public FlyAD_OBJProxy(int objsys_idx, UInt32 id, FlyADBase.FlyAD7 flyad)
            : base(objsys_idx)
        {
            ID = id;
            mFlyAD = flyad;
            mFlyAD.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(mFlyAD_PropertyChanged);
        }



        void mFlyAD_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if ((e.PropertyName == "LocalEP") ||
                (e.PropertyName == "HasCRC") ||
                (e.PropertyName == "GridSmooth") ||
                (e.PropertyName == "PosOfGrid") ||
                (e.PropertyName == "PosLen") ||
                (e.PropertyName == "MotorType") ||
                (e.PropertyName == "Ratio01") ||
                (e.PropertyName == "Ratio02") ||
                (e.PropertyName == "PosOffset") ||
                (e.PropertyName == "JogVelocity"))
            {
                FObjBase.PollModule.Current.Poll_JustOnce(
                    new PollModule.PollHandler(delegate()
                    {
                        byte[] buf;
                        GetValue(null, 0, FLYAD_OBJ_INTERFACE.GET_PARAMS, out buf);
                        CurrObjSys.PushObjInfoEx(
                            this, FLYAD_OBJ_INTERFACE.PUSH_PARAMS,
                            buf);
                    }), this, MARKNO_PUSH_PARAMS);
            }
        }
        #region FObj 重载
        public override void GetValue(IFConn from, uint srcid, ushort memid, out byte[] infodata)
        {
            infodata = null;
            switch (memid)
            {
                case FLYAD_OBJ_INTERFACE.GET_PARAMS:
                    {
                        mFlyAD.UpdateParam();

                        FLYAD_OBJ_INTERFACE.Pack_Params p = new FLYAD_OBJ_INTERFACE.Pack_Params()
                        {
                            ep = mFlyAD.LocalEP,
                            hasCRC = mFlyAD.HasCRC,
                            gridsmooth = mFlyAD.GridSmooth,
                            posofgrid = mFlyAD.PosOfGrid,
                            motortype = (MOTORTYPE) mFlyAD.MotorType,
                            poslen = mFlyAD.PosLen,
                            ratio01 = mFlyAD.Ratio01,
                            ratio02 = mFlyAD.Ratio02,
                            posoffset = mFlyAD.PosOffset,
                            jogvelocity = mFlyAD.JogVelocity
                        };


                        infodata = p.ToBytes();
                    }break;
                default:
                    infodata = null;
                    break;
            }
        }
        public override void SetValue(IFConn from, uint srcid, ushort memid, byte[] infodata)
        {
            switch (memid)
            {
                case FLYAD_OBJ_INTERFACE.SET_PARAMS:
                    {
                        FLYAD_OBJ_INTERFACE.Pack_Params p = new FLYAD_OBJ_INTERFACE.Pack_Params();
                        if (p.TryParse(infodata))
                        {
                            mFlyAD.HasCRC = p.hasCRC;
                            mFlyAD.GridSmooth = p.gridsmooth;
                            mFlyAD.Connect(p.ep);
                            mFlyAD.PosOffset = p.posoffset;
                            mFlyAD.JogVelocity = p.jogvelocity;
                            mFlyAD.PosOfGrid = p.posofgrid;
                            mFlyAD.MotorType = (FlyADBase.MOTORTYPE)p.motortype;
                            mFlyAD.Ratio01 = p.ratio01;
                            mFlyAD.Ratio02 = p.ratio02;
                            
                        }
                    } break;
            }
        }
        public override void CallFunction(IFConn from, uint srcid, uint magic, ushort funcid, byte[] infodata)
        {
            switch (funcid) 
            {
                case FLYAD_OBJ_INTERFACE.CALL_GETACCESSINFO:
                    {
                        GetAccessInfo(
                            new AsyncCBHandler(delegate(object AsyncState, object retdata)
                            {
                                ConnContext context = (ConnContext)AsyncState;
                                CurrObjSys.PushCallFunctionEx(
                                    context.from,
                                    context.srcid,
                                    ID,
                                    context.magic,
                                    FLYAD_OBJ_INTERFACE.CALL_GETACCESSINFO,
                                    ((AccessInfo)retdata).ToBytes());
                            }), new ConnContext(from, srcid, magic));

                    } break;
                case FLYAD_OBJ_INTERFACE.CALL_SETACCESS:
                    {
                        FLYAD_OBJ_INTERFACE.Pack_SetAccessRequest p = new FLYAD_OBJ_INTERFACE.Pack_SetAccessRequest();
                        if (!p.TryParse(infodata))
                            break;

                        SetAccess(
                            p.data,
                            new AsyncCBHandler(delegate(object AsyncState, object retdata)
                            {
                                ConnContext context = (ConnContext)AsyncState;
                                CurrObjSys.PushCallFunctionEx(
                                    context.from,
                                    context.srcid,
                                    ID,
                                    context.magic,
                                    FLYAD_OBJ_INTERFACE.CALL_SETACCESS,
                                    ((AccessInfo)retdata).ToBytes());
                            }), new ConnContext(from, srcid, magic));

                    } break;
                case FLYAD_OBJ_INTERFACE.CALL_GETGRID:
                    {
                        FLYAD_OBJ_INTERFACE.Pack_GetGridRequest p = new FLYAD_OBJ_INTERFACE.Pack_GetGridRequest();
                        if (!p.TryParse(infodata))
                            break;
                        GetGrid(
                            p.direction,
                            new AsyncCBHandler(delegate(object AsyncState, object retdata)
                            {
                                ConnContext context = (ConnContext)AsyncState;
                                CurrObjSys.PushCallFunctionEx(
                                    context.from,
                                    context.srcid,
                                    ID,
                                    context.magic,
                                    FLYAD_OBJ_INTERFACE.CALL_GETGRID,
                                    ((GridInfo)retdata).ToBytes());
                            }), new ConnContext(from, srcid, magic));
                    }break;
            }
        }
        #endregion

        /// <summary>
        /// 获取序列码
        /// </summary>
        /// <param name="AsyncDelegate">返回类型为 AccessInfo</param>
        /// <param name="AsyncState">可为null</param>
        void GetAccessInfo(AsyncCBHandler AsyncDelegate, object AsyncState)
        {
            AccessInfo ainfo = new AccessInfo()
            {
                status = (AREA_STATUS)mFlyAD.AreaStatus,
                ret = (AREA_ERR)mFlyAD.AreaRet,
                surplus = (UInt16)mFlyAD.Surplus,
                code = mFlyAD.Code,
                access = mFlyAD.Access
            };
            AsyncDelegate(AsyncState, ainfo);
        }
        class AsyncDelegateObj
        {
            public AsyncCBHandler AsyncDelegate;
            public object AsyncState;
        }
        List<AsyncDelegateObj> setAccessRetList = new List<AsyncDelegateObj>();

        PropertyChangedEventHandler mFlyAD_PropertyChangedHandler = null;
        /// <summary>
        /// 设置授权码
        /// </summary>
        /// <param name="access">授权码</param>
        /// <param name="AsyncDelegate">返回类型为 AccessInfo</param>
        /// <param name="AsyncState">可为null</param>
        void SetAccess(byte[] access, AsyncCBHandler AsyncDelegate, object AsyncState)
        {
            mFlyAD.SetAccess(access);
            setAccessRetList.Add(new AsyncDelegateObj() { AsyncDelegate = AsyncDelegate, AsyncState = AsyncState });

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

        /// <summary>
        /// 获取grid
        /// </summary>
        /// <param name="direction">方向</param>
        /// <param name="AsyncDelegate">返回类型为 byte[]</param>
        /// <param name="AsyncState">可为null</param>
        void GetGrid(Misc.DIRECTION direction, AsyncCBHandler AsyncDelegate, object AsyncState) 
        {
            int[] dat;
            mFlyAD.GetGrid(direction, out dat);
            GridInfo p = new GridInfo()
            {
                data = dat,
                direction = direction,
                grid_start = 0,
                isall = true
            };
            AsyncDelegate(AsyncState, p);
        }
    }
}
