using FLY.OBJComponents.Common;
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 SyncPropServiceClient : FObj
    {
        Dictionary<string, INotifyPropertyChanged> ObjNames;

        IFConn mConn;
        UInt32 mServerID;

        //public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// 当前 INotifyPropertyChanged 对象 引发了 PropertyChanged,  是由于 接收到数据导致的
        /// </summary>
        public bool IsInPushValue { get;protected set; }


        public SyncPropServiceClient(UInt32 serverID, Dictionary<string, INotifyPropertyChanged> objnames)
        {
            mServerID = serverID;
            Init(objnames);
        }
        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="objnames"></param>
        void Init(Dictionary<string, INotifyPropertyChanged> objnames)
        {
            ObjNames = objnames;

            foreach (INotifyPropertyChanged obj in ObjNames.Values)
            {
                obj.PropertyChanged += Data_PropertyChanged;
            }
        }
        /// <summary>
        /// 在Init后，删除某个obj
        /// </summary>
        /// <param name="objname"></param>
        public void Remove(string objname)
        {
            ObjNames[objname].PropertyChanged -= Data_PropertyChanged;
            ObjNames.Remove(objname);
        }
        /// <summary>
        /// 在Init后，添加某个obj
        /// </summary>
        public void Add(string objname, INotifyPropertyChanged obj)
        {
            ObjNames.Add(objname, obj);

            //向服务器，只获取这个对象的数据
            string json = JsonConvert.SerializeObject(objname);
            FObjBase.FObjSys.Current.CallFunctionEx(mConn, mServerID, ID, SYNCPROP_OBJ_INTERFACE.CALL_GET_DATA,
                Misc.Converter.StringToBytes(json));
        }
        /// <summary>
        /// 属性变化时通知
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Data_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            string objname = (from kv in ObjNames where kv.Value == sender select kv.Key).First();

            Dictionary<string, Dictionary<string, object>> DsDso = new Dictionary<string, Dictionary<string, object>>
            {
                {
                    objname, new Dictionary<string, object>
                    {
                        {e.PropertyName, Misc.PropertiesManager.GetValue(sender, e.PropertyName)}
                    }
                }
            };

            string json = JsonConvert.SerializeObject(DsDso);
            FObjBase.FObjSys.Current.CallFunctionEx(mConn, mServerID, ID, SYNCPROP_OBJ_INTERFACE.CALL_SET_DATA,
                Misc.Converter.StringToBytes(json));
        }

        public override void ConnectNotify(IFConn from)
        {
            mConn = from;
            
            if (from.IsConnected)
            {
                CurrObjSys.CallFunctionEx(mConn, mServerID, ID,
                    SYNCPROP_OBJ_INTERFACE.CALL_GET_ALL_DATA, null);


                CurrObjSys.SenseConfigEx(mConn, mServerID, ID,
                    0xffffffff, SENSE_CONFIG.ADD);
            }
        }

        public override void PushInfo(IFConn from, uint srcid, ushort infoid, byte[] infodata)
        {
            switch (infoid)
            {
                case SYNCPROP_OBJ_INTERFACE.PUSH_DATA:
                    {
                        string json = Misc.Converter.BytesToString(infodata);
                        Dictionary<string, Dictionary<string, object>> DsDso = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, object>>>(json);
                        IsInPushValue = true;
                        foreach (var Dso in DsDso)
                        {
                            INotifyPropertyChanged obj = ObjNames[Dso.Key] as INotifyPropertyChanged;
                            obj.PropertyChanged -= Data_PropertyChanged;
                            
                            foreach (var dv in Dso.Value)
                            {
                                PropertiesManager_JSON.SetValue(obj, dv.Key, dv.Value);
                            }
                            
                            obj.PropertyChanged += Data_PropertyChanged;
                        }
                        IsInPushValue = false;
                    }
                    break;
            }
        }

        public override void PushCallFunction(IFConn from, uint srcid, uint magic, ushort funcid, byte[] retdata, object AsyncDelegate, object AsyncState)
        {
            switch (funcid)
            {
                case SYNCPROP_OBJ_INTERFACE.CALL_GET_ALL_DATA:
                    {
                        string json = Misc.Converter.BytesToString(retdata);
                        Dictionary<string, Dictionary<string, object>> DsDso = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, object>>>(json);
                        IsInPushValue = true;
                        foreach (var Dso in DsDso)
                        {
                            if (ObjNames.ContainsKey(Dso.Key))
                            {
                                INotifyPropertyChanged obj = ObjNames[Dso.Key] as INotifyPropertyChanged;
                                obj.PropertyChanged -= Data_PropertyChanged;
                                foreach (var dv in Dso.Value)
                                {
                                    PropertiesManager_JSON.SetValue(obj, dv.Key, dv.Value);
                                }
                                obj.PropertyChanged += Data_PropertyChanged;
                            }
                        }
                        IsInPushValue = false;
                    }
                    break;
            }
        }
    }
    
}
