using FLY.OBJComponents.IService;
using FLY.OBJComponents.OBJ_INTERFACE;
using FObjBase;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace FLY.OBJComponents.Client
{
    public class PLCProxySystemServiceClient : FObj, IPLCProxySystemService, IPropertyOpt
    {
        public Dictionary<string, INotifyPropertyChanged> ObjNames { get; private set; }

        public bool IsConnected { get; private set; } = false;

        SyncPropServiceClient syncPropServiceClient;
        /// <summary>
        /// 与PLC连接成功
        /// </summary>
        public bool IsConnectedWithPLC { get; set; } = false;

        IFConn mConn;
        UInt32 mServerID;

        public event PropertyChangedEventHandler PropertyChanged;

        public PLCProxySystemServiceClient(UInt32 serverID, Dictionary<string, INotifyPropertyChanged> objnames)
        {
            mServerID = serverID;
            ObjNames = objnames;

            syncPropServiceClient = new SyncPropServiceClient(
                serverID + 1,
                new Dictionary<string, INotifyPropertyChanged> {
                    {".", this }
                });
        }
        public UInt32[] GetIDs()
        {
            return new UInt32[] { ID,
                syncPropServiceClient.ID
            };
        }


        public override void ConnectNotify(IFConn from)
        {
            mConn = from;

            IsConnected = from.IsConnected;
            if (from.IsConnected)
            {
                CurrObjSys.SenseConfigEx(mConn, mServerID, ID,
                    0xffffffff, SENSE_CONFIG.ADD);
            }
        }

        #region IPLCProxySystemService
        public void FeedPlan(long planID)
        {
            PLCOS_OBJ_INTERFACE.Pack_FeedPlanRequest pack = new PLCOS_OBJ_INTERFACE.Pack_FeedPlanRequest()
            {
                planid = planID
            };
            string json = JsonConvert.SerializeObject(pack);

            FObjSys.Current.CallFunctionEx(mConn, mServerID, ID,
                PLCOS_OBJ_INTERFACE.CALL_FEED_PLAN, Misc.Converter.StringToBytes(json));
        }
        public void RemovePlan(long planID)
        {
            PLCOS_OBJ_INTERFACE.Pack_RemovePlanRequest pack = new PLCOS_OBJ_INTERFACE.Pack_RemovePlanRequest()
            {
                planid = planID
            };
            string json = JsonConvert.SerializeObject(pack);

            FObjSys.Current.CallFunctionEx(mConn, mServerID, ID,
                PLCOS_OBJ_INTERFACE.CALL_REMOVE_PLAN, Misc.Converter.StringToBytes(json));
        }

        public void SetPlan(string objname, IEnumerable<string> propertynames, long planID)
        {
            PLCOS_OBJ_INTERFACE.Pack_SetPlanRequest pack = new PLCOS_OBJ_INTERFACE.Pack_SetPlanRequest()
            {
                objname = objname,
                propertyNames = propertynames,
                planid = planID
            };
            string json = JsonConvert.SerializeObject(pack);

            FObjSys.Current.CallFunctionEx(mConn, mServerID, ID,
                PLCOS_OBJ_INTERFACE.CALL_SET_PLAN, Misc.Converter.StringToBytes(json));
        }

        /// <summary>
        /// 设置更新计划
        /// </summary>
        /// <param name="objname">对象名</param>
        /// <param name="propertynames">属性名</param>
        /// <param name="planID">计划的编号,应该全局唯一,建议使用时间ticks</param>
        public void SetPlan(string objname, IEnumerable<string> propertynames, SetPlanReponseHandler setPlanReponse, object context)
        {
            PLCOS_OBJ_INTERFACE.Pack_SetPlan2Request pack = new PLCOS_OBJ_INTERFACE.Pack_SetPlan2Request()
            {
                objname = objname,
                propertyNames = propertynames,
            };

            string json = JsonConvert.SerializeObject(pack);

            FObjSys.Current.CallFunctionEx(mConn, mServerID, ID,
                PLCOS_OBJ_INTERFACE.CALL_SET_PLAN2, Misc.Converter.StringToBytes(json), setPlanReponse, context);
        }
        #endregion

        public string[] GetSyncPropNames()
        {
            return new string[] {
                "IsConnectedWithPLC"
            };
        }

        public string[] GetNoSyncPropNames()
        {
            return null;
        }

        public override void PushCallFunction(IFConn from, uint srcid, uint magic, ushort funcid, byte[] retdata, object AsyncDelegate, object AsyncState)
        {
            switch (funcid)
            {
                case PLCOS_OBJ_INTERFACE.CALL_SET_PLAN2:
                    {
                        string json = Misc.Converter.BytesToString(retdata);
                        PLCOS_OBJ_INTERFACE.Pack_SetPlan2Reponse reponse = JsonConvert.DeserializeObject<PLCOS_OBJ_INTERFACE.Pack_SetPlan2Reponse>(json);
                        SetPlanReponseHandler setPlanReponseHandler = (SetPlanReponseHandler)AsyncDelegate;


                        setPlanReponseHandler(reponse.planid, AsyncState);
                    }
                    break;
            }
        }

    }
}