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.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace FLY.OBJComponents.Client
{
    public class BufferServiceClient<T> : FObj, IBuffer<T>
    {
        #region property
        public int NewestID { get; private set; } = 0;
        public int Count { get; private set; } = 0;
        /// <summary>
        /// 总容量，当总数量 大于等于 总容量的 100%， 前面的10%数据会被删除
        /// </summary>
        public int Capacity { get; set; } = 1000;
        #endregion
        public event NotifyBufferChangedEventHandler<T> BufferChanged;
        public event PropertyChangedEventHandler PropertyChanged;

        IFConn mConn;
        UInt32 mServerID;

        /// <summary>
        /// 数据是从服务器推送过来的，忽略属性变化事件
        /// </summary>
        bool isIgnore = false;

        public BufferServiceClient(UInt32 serverid)
        {
            mServerID = serverid;
            this.PropertyChanged += BufferServiceClient_PropertyChanged;
        }

        private void BufferServiceClient_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (isIgnore)
                return;
            Dictionary<string, object> datas = new Dictionary<string, object>();
            datas.Add(e.PropertyName, Misc.PropertiesManager.GetValue(sender, e.PropertyName));
            string json = JsonConvert.SerializeObject(datas);
            

            CurrObjSys.SetValueEx(mConn, mServerID, ID, BUFFER_OBJ_INTERFACE.SET_PARAMS,
                Misc.Converter.StringToBytes(json));
        }

        public override void Dispose()
        {
            CurrObjSys.ObjRemove(
                this, mConn);
        }
        public override void ConnectNotify(IFConn from)
        {
            mConn = from;
            if (from.IsConnected)
            {
                //获取所有数据，设置推送
                CurrObjSys.GetValueEx(
                    mConn, mServerID, ID,
                    BUFFER_OBJ_INTERFACE.GET_PARAMS);

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

                BufferChanged?.Invoke(this, new NotifyBufferChangedEventArgs<T>()
                {
                    Action = NotifyBufferChangedAction.IsConnected
                });
            }
        }

        public override void PushGetValue(IFConn from, uint srcid, ushort memid, byte[] infodata)
        {
            switch (memid)
            {

                case BUFFER_OBJ_INTERFACE.GET_PARAMS:
                    {
                        string json = Misc.Converter.BytesToString(infodata);

                        Dictionary<string, object> datas = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);

                        isIgnore = true;

                        foreach (KeyValuePair<string, object> kv in datas)
                        {
                            PropertiesManager_JSON.SetValue(this, kv.Key, kv.Value);
                        }

                        isIgnore = false;
                    }
                    break;

            }
        }
        public override void PushInfo(IFConn from, uint srcid, ushort infoid, byte[] infodata)
        {
            switch (infoid)
            {
                case BUFFER_OBJ_INTERFACE.PUSH_PARAMS:
                    {
                        PushGetValue(from, srcid, infoid, infodata);
                    }
                    break;
                case BUFFER_OBJ_INTERFACE.PUSH_BUFFERCHANGED:
                    {
                        string json = Misc.Converter.BytesToString(infodata);
                        NotifyBufferChangedEventArgs<T> p = JsonConvert.DeserializeObject<NotifyBufferChangedEventArgs<T>>(json);
                        BufferChanged?.Invoke(this, p);
                    }
                    break;
            }

        }
        public override void PushCallFunction(IFConn from, uint srcid, uint magic, ushort funcid, byte[] retdata, object AsyncDelegate, object AsyncState)
        {
            switch (funcid)
            {
                case BUFFER_OBJ_INTERFACE.CALL_GETRECORD:
                    {
                        string json = Misc.Converter.BytesToString(retdata);
                        GetRecordReponse<T> p = JsonConvert.DeserializeObject<GetRecordReponse<T>>(json);
                        ((AsyncCBHandler)AsyncDelegate)(AsyncState, p);
                    }
                    break;
                case BUFFER_OBJ_INTERFACE.CALL_GETRECORD_NEWEST:
                    {
                        string json = Misc.Converter.BytesToString(retdata);
                        GetRecordReponse<T> p = JsonConvert.DeserializeObject<GetRecordReponse<T>>(json);
                        ((AsyncCBHandler)AsyncDelegate)(AsyncState, p);
                    }
                    break;
            }
        }

        public void Reset()
        {
            CurrObjSys.CallFunctionEx(mConn, mServerID, ID, BUFFER_OBJ_INTERFACE.CALL_RESET, null);
        }

        public void GetRecord(int last_id, int count, AsyncCBHandler asyncCB, object asyncContext)
        {
            BUFFER_OBJ_INTERFACE.Pack_GetRecordRequest request = new BUFFER_OBJ_INTERFACE.Pack_GetRecordRequest() { last_id = last_id, count = count };
            string json = JsonConvert.SerializeObject(request);

            CurrObjSys.CallFunctionEx(mConn, mServerID, ID, BUFFER_OBJ_INTERFACE.CALL_GETRECORD,
                Misc.Converter.StringToBytes(json),
                asyncCB, asyncContext
                );
        }
        public void GetRecord(int count, AsyncCBHandler asyncCB, object asyncContext)
        {
            BUFFER_OBJ_INTERFACE.Pack_GetRecordNewestRequest request = new BUFFER_OBJ_INTERFACE.Pack_GetRecordNewestRequest() { count = count };
            string json = JsonConvert.SerializeObject(request);

            CurrObjSys.CallFunctionEx(mConn, mServerID, ID, BUFFER_OBJ_INTERFACE.CALL_GETRECORD_NEWEST,
                Misc.Converter.StringToBytes(json),
                asyncCB, asyncContext
                );
        }
    }
}
