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
    {
        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)
        {
            Dictionary<string, object> p = new Dictionary<string, object>();
            p.Add(e.PropertyName, Misc.PropertiesManager.GetValue(buffer, e.PropertyName));
            
            string json = JsonConvert.SerializeObject(p);
            CurrObjSys.PushObjInfoEx(
                this, BUFFER_OBJ_INTERFACE.PUSH_PARAMS,
                Misc.Converter.StringToBytes(json)
                );
        }

        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);

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

                        foreach (var kv in p)
                        {
                            PropertiesManager_JSON.SetValue(buffer, kv.Key, kv.Value);
                        }
                    }
                    break;
                default:
                    infodata = null;
                    break;
            }
        }

        public override void GetValue(IFConn from, uint srcid, ushort memid, out byte[] infodata)
        {
            switch (memid)
            {
                case BUFFER_OBJ_INTERFACE.GET_PARAMS:
                    {
                        Dictionary<string, object> p = new Dictionary<string, object>();
                        IEnumerable<string> propertynames = Misc.PropertiesManager.GetAllPropertyNames(buffer);
                        foreach (string pn in propertynames)
                        {
                            p.Add(pn, Misc.PropertiesManager.GetValue(buffer, pn));
                        }
                        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;
                                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_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;
            }
        }
    }
}