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; } = -1;
        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;


        public BufferServiceClient(UInt32 serverid)
        {
            mServerID = serverid;
        }

        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.GetValueEx(
                    mConn, mServerID, ID,
                    BUFFER_OBJ_INTERFACE.GET_STATUS);

                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);
                        var p = Newtonsoft.Json.JsonConvert.DeserializeObject<BUFFER_OBJ_INTERFACE.Pack_Params>(json);
                        Capacity = p.capcity;
                    }
                    break;
                case BUFFER_OBJ_INTERFACE.GET_STATUS:
                    {
                        string json = Misc.Converter.BytesToString(infodata);
                        var p = Newtonsoft.Json.JsonConvert.DeserializeObject<BUFFER_OBJ_INTERFACE.Pack_Status>(json);
                        Count = p.count;
                        NewestID = p.newestId;
                    }
                    break;

            }
        }
        public override void PushInfo(IFConn from, uint srcid, ushort infoid, byte[] infodata)
        {
            switch (infoid)
            {
                case BUFFER_OBJ_INTERFACE.PUSH_STATUS:
                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:
                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
                );
        }
    
        public void Apply()
        {
            var p = new BUFFER_OBJ_INTERFACE.Pack_Params()
            {
                capcity = Capacity
            };
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(p);
            CurrObjSys.SetValueEx(mConn, mServerID, ID, BUFFER_OBJ_INTERFACE.SET_PARAMS,
                Misc.Converter.StringToBytes(json));
        }
    }
}
