using FLY.OBJComponents.Common;
using FLY.OBJComponents.IService;
using FLY.OBJComponents.OBJ_INTERFACE;
using FLY.Thick.RemoteHistory;
using FObjBase;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FLY.OBJComponents.Server.OBJProxy
{
    public class Buffer_OBJProxy<T> : FObj
    {
        const int MARKNO_PUSH_STATUS = 1;
        const int MARKNO_PUSH_PARAMS = 2;
        IBuffer<T> buffer;

        public Buffer_OBJProxy(int objsys_idx, UInt32 id, IBuffer<T> buffer)
            : base(objsys_idx)
        {
            ID = id;
            this.buffer = buffer;
            buffer.BufferChanged += Buffer_BufferChanged;
            buffer.PropertyChanged += Buffer_PropertyChanged;
        }

        private void Buffer_BufferChanged(object sender, NotifyBufferChangedEventArgs<T> e)
        {
            string j = JsonConvert.SerializeObject(e);

            CurrObjSys.PushObjInfoEx(
                this, BUFFER_OBJ_INTERFACE.PUSH_BUFFERCHANGED,
                Misc.Converter.StringToBytes(j));
        }

        private void Buffer_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if ((e.PropertyName == "NewestID") ||
                (e.PropertyName == "Count"))
            {
                FObjBase.PollModule.Current.Poll_JustOnce(() =>
                {
                    byte[] buf;
                    GetValue(null, 0, BUFFER_OBJ_INTERFACE.GET_STATUS, out buf);
                    CurrObjSys.PushObjInfoEx(
                        this, BUFFER_OBJ_INTERFACE.GET_STATUS,
                        buf);
                }, this, MARKNO_PUSH_STATUS);
            }
            if (e.PropertyName == "Capacity")
            {
                FObjBase.PollModule.Current.Poll_JustOnce(() =>
                {
                    byte[] buf;
                    GetValue(null, 0, BUFFER_OBJ_INTERFACE.GET_PARAMS, out buf);
                    CurrObjSys.PushObjInfoEx(
                        this, BUFFER_OBJ_INTERFACE.GET_PARAMS,
                        buf);
                }, this, MARKNO_PUSH_PARAMS);
            }
        }

        public override void SetValue(IFConn from, uint srcid, ushort memid, byte[] infodata)
        {
            switch (memid)
            {
                case BUFFER_OBJ_INTERFACE.SET_PARAMS:
                    {
                        string json = Misc.Converter.BytesToString(infodata);
                        var p = Newtonsoft.Json.JsonConvert.DeserializeObject<BUFFER_OBJ_INTERFACE.Pack_Params>(json);
                        buffer.Capacity = p.capcity;
                    }
                    break;
            }
        }

        public override void GetValue(IFConn from, uint srcid, ushort memid, out byte[] infodata)
        {
            switch (memid)
            {
                case BUFFER_OBJ_INTERFACE.GET_PARAMS:
                    {
                        var p = new BUFFER_OBJ_INTERFACE.Pack_Params()
                        {
                            capcity = buffer.Capacity
                        };
                        string json = JsonConvert.SerializeObject(p);
                        infodata = Misc.Converter.StringToBytes(json);
                    }
                    break;
                case BUFFER_OBJ_INTERFACE.GET_STATUS:
                    {
                        var p = new BUFFER_OBJ_INTERFACE.Pack_Status()
                        {
                            newestId = buffer.NewestID,
                            count = buffer.Count
                        };
                        string json = JsonConvert.SerializeObject(p);
                        infodata = Misc.Converter.StringToBytes(json);
                    }
                    break;
                default:
                    infodata = null;
                    break;
            }
        }

        public override void CallFunction(IFConn from, uint srcid, uint magic, ushort funcid, byte[] infodata)
        {
            switch (funcid)
            {
                case BUFFER_OBJ_INTERFACE.CALL_GETRECORD:
                    {
                        string json = Misc.Converter.BytesToString(infodata);
                        BUFFER_OBJ_INTERFACE.Pack_GetRecordRequest request = JsonConvert.DeserializeObject<BUFFER_OBJ_INTERFACE.Pack_GetRecordRequest>(json);
                        buffer.GetRecord(request.last_id, request.count,
                            (asyncContext, retData) =>
                            {
                                ConnContext connContext = asyncContext as ConnContext;
                                string j = JsonConvert.SerializeObject(retData);
                                CurrObjSys.PushCallFunctionEx(
                                    connContext.from, 
                                    connContext.srcid, ID, 
                                    connContext.magic, BUFFER_OBJ_INTERFACE.CALL_GETRECORD, Misc.Converter.StringToBytes(j));

                            }, new ConnContext(from, srcid, magic));
                        
                    }
                    break;
                case BUFFER_OBJ_INTERFACE.CALL_GETRECORD_NEWEST:
                    {
                        string json = Misc.Converter.BytesToString(infodata);
                        BUFFER_OBJ_INTERFACE.Pack_GetRecordNewestRequest request = JsonConvert.DeserializeObject<BUFFER_OBJ_INTERFACE.Pack_GetRecordNewestRequest>(json);
                        buffer.GetRecord(request.count,
                            (asyncContext, retData) =>
                            {
                                ConnContext connContext = asyncContext as ConnContext;
                                GetRecordReponse<T> reponse = retData as GetRecordReponse<T>;
                                string j = JsonConvert.SerializeObject(reponse);
                                CurrObjSys.PushCallFunctionEx(
                                    connContext.from,
                                    connContext.srcid, ID,
                                    connContext.magic, funcid, Misc.Converter.StringToBytes(j));

                            }, new ConnContext(from, srcid, magic));

                    }
                    break;
                case BUFFER_OBJ_INTERFACE.CALL_RESET:
                    {
                        buffer.Reset();
                    }break;
            }
        }
    }
}
