using FLY.OBJComponents.Common;
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.Server.OBJProxy
{
    /// <summary>
    /// 同步属性 OBJ协议代理
    /// </summary>
    public class SyncProp_OBJProxy : FObj
    {

        Dictionary<string, INotifyPropertyChanged> ObjNames;

        public SyncProp_OBJProxy(int objsys_idx, UInt32 serverID, Dictionary<string, INotifyPropertyChanged> objnames) : base(objsys_idx)
        {
            ID = serverID;
            ObjNames = objnames;
            Init();
        }
        void Init()
        {
            foreach (var obj in ObjNames.Values)
            {
                obj.PropertyChanged += Data_PropertyChanged;
            }
        }
        /// <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.PushObjInfoEx(this, SYNCPROP_OBJ_INTERFACE.PUSH_DATA,
                Misc.Converter.StringToBytes(json));
        }
        Dictionary<string, object> GetDso(object obj)
        {
            List<string> dnames = new List<string>();
            if (obj is IPropertyOpt)
            {
                IPropertyOpt opt = obj as IPropertyOpt;
                IEnumerable<string> sync = opt.GetSyncPropNames();
                if (sync == null)
                {
                    dnames.AddRange(Misc.PropertiesManager.GetAllPropertyNames(obj));

                    string[] nosync = opt.GetNoSyncPropNames();
                    if (nosync != null)
                    {
                        dnames.RemoveAll(n => nosync.Contains(n));
                    }
                }
                else
                    dnames.AddRange(sync);
            }
            else
            {
                dnames.AddRange(Misc.PropertiesManager.GetAllPropertyNames(obj));
            }

            Dictionary<string, object> Dso = new Dictionary<string, object>();
            foreach (string dn in dnames)
            {
                object val = Misc.PropertiesManager.GetValue(obj, dn);
                Dso.Add(dn, val);
            }
            return Dso;
        }
        public override void CallFunction(IFConn from, uint srcid, uint magic, ushort funcid, byte[] infodata)
        {
            switch (funcid)
            {
                case SYNCPROP_OBJ_INTERFACE.CALL_GET_ALL_DATA:
                    {
                        Dictionary<string, Dictionary<string, object>> DsDso = new Dictionary<string, Dictionary<string, object>>();

                        foreach (var kv in ObjNames)
                        {
                            DsDso.Add(kv.Key, GetDso(kv.Value));
                        }
                        string json = JsonConvert.SerializeObject(DsDso);

                        FObjBase.FObjSys.Current.PushCallFunctionEx(from, srcid, this.ID, magic, funcid, Misc.Converter.StringToBytes(json));
                    }
                    break;
                case SYNCPROP_OBJ_INTERFACE.CALL_GET_DATA:
                    {
                        string json = Misc.Converter.BytesToString(infodata);
                        string objname = JsonConvert.DeserializeObject<string>(json);


                        Dictionary<string, Dictionary<string, object>> DsDso = new Dictionary<string, Dictionary<string, object>>();

                        INotifyPropertyChanged obj = ObjNames[objname];

                        DsDso.Add(objname, GetDso(obj));

                        json = JsonConvert.SerializeObject(DsDso);

                        FObjBase.FObjSys.Current.PushCallFunctionEx(from, srcid, this.ID, magic, funcid, Misc.Converter.StringToBytes(json));
                    }
                    break;
                case SYNCPROP_OBJ_INTERFACE.CALL_SET_DATA:
                    {
                        string json = Misc.Converter.BytesToString(infodata);
                        Dictionary<string, Dictionary<string, object>> DsDso = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, object>> > (json);

                        foreach (var Dso in DsDso)
                        {
                            object obj = ObjNames[Dso.Key];
                            foreach (var dv in Dso.Value)
                            {
                                PropertiesManager_JSON.SetValue(obj, dv.Key, dv.Value);
                            }
                        }
                    }
                    break;
            }
        }

    }
}