using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FObjBase;

namespace FLY.Thick.BulkDataModule
{
    public class BulkDataService_OBJProxy : FObj
    {
        #region 延时推送 MARKNO
        const int MARKNO_PUSH_PARAMS = 1;
        #endregion


        IBulkDataService mBulkData;


        public BulkDataService_OBJProxy(int objsys_idx, UInt32 id, IBulkDataService bulkdata)
            : base(objsys_idx)
        {
            mBulkData = bulkdata;
            ID = id;

            mBulkData.DatasChanged += MBulkData_DatasChanged;
            mBulkData.PropertyChanged += MBulkData_PropertyChanged;
        }

        private void MBulkData_DatasChanged(object sender, NotifyDatasChangedEventArgs e)
        {
            BULKDATA_OBJ_INTERFACE.Pack_PushChanged p = new BULKDATA_OBJ_INTERFACE.Pack_PushChanged();
            p.Action = e.Action;
            switch (e.Action)
            {
                case NotifyDatasChangedAction.Add:
                    p.data = e.Items[0] as FR_DATA;
                    break;
                case NotifyDatasChangedAction.Replace:
                    p.data = e.Items[0] as FR_DATA;
                    break;
                case NotifyDatasChangedAction.Reset:
                    break;
            }
            CurrObjSys.PushObjInfoEx(this, BULKDATA_OBJ_INTERFACE.PUSH_CHANGED, p.ToBytes());
        }

        private void MBulkData_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if ((e.PropertyName == "Count") || (e.PropertyName == "CurrentBookmark"))
            {
                FObjBase.PollModule.Current.Poll_JustOnce(
                    new PollModule.PollHandler(delegate ()
                    {
                        byte[] buf;
                        GetValue(null, 0, BULKDATA_OBJ_INTERFACE.GET_PARAMS, out buf);
                        CurrObjSys.PushObjInfoEx(
                            this, BULKDATA_OBJ_INTERFACE.PUSH_PARAMS,
                            buf);
                    }), this, MARKNO_PUSH_PARAMS);
            }
        }


        #region IFObj 成员

        public override void ConnectNotify(IFConn from)
        {
            //TODO, 当from 断线后，应该删除关于它的推送
            if (!from.IsConnected) 
            {
                mBulkData.ClosePush(delegate(object AsyncState)
                {
                    if (!(AsyncState is ConnContext))
                        return false;
                    ConnContext context = (ConnContext)AsyncState;
                    if (context.from != from)
                        return false;

                    return true;
                });
            }
        }

        public override void CallFunction(IFConn from, uint srcid, UInt32 magic, ushort funcid, byte[] infodata)
        {
            switch (funcid)
            {
                case BULKDATA_OBJ_INTERFACE.CALL_PUSH_NEWFRAMEDATA:
                    {
                        BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataParam pack = new BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataParam();

                        if (!pack.TryParse(infodata))
                            return;

                        mBulkData.PushNewFrameData(
                            pack,
                            delegate(object AsyncState, object retData)
                            {
                                ConnContext context = (ConnContext)AsyncState;
                                CurrObjSys.PushCallFunctionEx(
                                    context.from,
                                    context.srcid,
                                    ID,
                                    context.magic,
                                    BULKDATA_OBJ_INTERFACE.CALL_PUSH_NEWFRAMEDATA,
                                    ((BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataReturn)retData).ToBytes());
                            }, new ConnContext(from, srcid, magic));
                    }break;
                case BULKDATA_OBJ_INTERFACE.CALL_CLOSE_PUSH_NEWFRAMEDATA:
                    {
                        BULKDATA_OBJ_INTERFACE.Pack_CallClosePushNewFrameData pack = new BULKDATA_OBJ_INTERFACE.Pack_CallClosePushNewFrameData();

                        if (!pack.TryParse(infodata))
                            return;

                        mBulkData.ClosePushNewFrameData(
                            pack,
                            new ConnContext(from, srcid, magic));
                    }break;
                case BULKDATA_OBJ_INTERFACE.CALL_GET_FRAMEDATA:
                    {
                        BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam pack = new BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam();

                        if (!pack.TryParse(infodata))
                            return;

                        mBulkData.GetFrameData(
                            pack, 
                            delegate(object AsyncState, object retData)
                            {
                                ConnContext context = (ConnContext)AsyncState;
                                CurrObjSys.PushCallFunctionEx(
                                    context.from,
                                    context.srcid,
                                    ID,
                                    context.magic,
                                    BULKDATA_OBJ_INTERFACE.CALL_GET_FRAMEDATA,
                                    ((BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataReturn)retData).ToBytes());
                            }, new ConnContext(from, srcid, magic));
                        
                    } break;
                case BULKDATA_OBJ_INTERFACE.CALL_CLOSE_PUSH_FRAMEDATA:
                    {
                        BULKDATA_OBJ_INTERFACE.Pack_CallClosePushFrameData pack = new BULKDATA_OBJ_INTERFACE.Pack_CallClosePushFrameData();

                        if (!pack.TryParse(infodata))
                            return;

                         mBulkData.ClosePushFrameData(
                             pack, 
                             new ConnContext(from, srcid, magic));
                    
                    } break;
                case BULKDATA_OBJ_INTERFACE.CALL_GET_TRENDDATA:
                    {
                        BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataParam pack = new BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataParam();

                        if (!pack.TryParse(infodata))
                            return;

                        mBulkData.GetTrendData(
                            pack,
                            delegate(object AsyncState, object retData)
                            {
                                ConnContext context = (ConnContext)AsyncState;
                                CurrObjSys.PushCallFunctionEx(
                                    context.from,
                                    context.srcid,
                                    ID,
                                    context.magic,
                                    BULKDATA_OBJ_INTERFACE.CALL_GET_TRENDDATA,
                                    ((BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataReturn)retData).ToBytes());

                            }, new ConnContext(from, srcid, magic));
                    } break;
                case BULKDATA_OBJ_INTERFACE.CALL_CLOSE_PUSH_TRENDDATA:
                    {
                        BULKDATA_OBJ_INTERFACE.Pack_CallClosePushTrendData pack = new BULKDATA_OBJ_INTERFACE.Pack_CallClosePushTrendData();

                        if (!pack.TryParse(infodata))
                            return;
                        mBulkData.ClosePushTrendData(
                            pack,
                            new ConnContext(from, srcid, magic));
                    
                    } break;
                case BULKDATA_OBJ_INTERFACE.CALL_CLEAR:
                    {
                        mBulkData.Clear();
                    } break;
                case BULKDATA_OBJ_INTERFACE.CALL_GET_FRAMEDATAMIX:
                    {
                        Pack_CallGetFrameDataMixRequest pack = new Pack_CallGetFrameDataMixRequest();

                        if (!pack.TryParse(infodata))
                            return;

                        mBulkData.GetFrameDataMix(
                            pack,
                            delegate (object AsyncState, object retData)
                            {
                                ConnContext context = (ConnContext)AsyncState;
                                CurrObjSys.PushCallFunctionEx(
                                    context.from,
                                    context.srcid,
                                    ID,
                                    context.magic,
                                    BULKDATA_OBJ_INTERFACE.CALL_GET_FRAMEDATAMIX,
                                    ((Pack_CallGetFrameDataMixReponse)retData).ToBytes());
                            }, new ConnContext(from, srcid, magic));
                    }
                    break;
                case BULKDATA_OBJ_INTERFACE.CALL_CLOSE_PUSH_FRAMEDATAMIX:
                    {
                        Pack_CallClosePushFrameDataMixRequest pack = new Pack_CallClosePushFrameDataMixRequest();

                        if (!pack.TryParse(infodata))
                            return;

                        mBulkData.ClosePushFrameDataMix(
                            pack,
                            new ConnContext(from, srcid, magic));

                    }
                    break;
                case BULKDATA_OBJ_INTERFACE.CALL_GET_LIST_NEW_10:
                    {
                        BULKDATA_OBJ_INTERFACE.Pack_CallGetListReponse p
                            = new BULKDATA_OBJ_INTERFACE.Pack_CallGetListReponse();
                            
                        int cnt = mBulkData.Datas.Count;
                        if (cnt > 0)
                        {
                            if (cnt > 10)
                                cnt = 10;
                            p.list.AddRange(mBulkData.Datas.Skip(mBulkData.Datas.Count - cnt));
                        }
                        CurrObjSys.PushCallFunctionEx(from, srcid, ID, magic, funcid, p.ToBytes());
                    }
                    break;
                case BULKDATA_OBJ_INTERFACE.CALL_GET_LIST_OTHER:
                    {
                        BULKDATA_OBJ_INTERFACE.Pack_CallGetListReponse p
                            = new BULKDATA_OBJ_INTERFACE.Pack_CallGetListReponse();

                        int cnt = mBulkData.Datas.Count;
                        if (cnt > 10)
                        {
                            p.list.AddRange(mBulkData.Datas.Take(cnt - 10));
                        }
                        CurrObjSys.PushCallFunctionEx(from, srcid, ID, magic, funcid, p.ToBytes());
                    }
                    break;
            }
        }

        public override void GetValue(IFConn from, uint srcid, ushort memid, out byte[] infodata)
        {
            infodata = null;
            switch (memid)
            {
                case BULKDATA_OBJ_INTERFACE.GET_PARAMS:
                    {
                        BULKDATA_OBJ_INTERFACE.Pack_Params p = new BULKDATA_OBJ_INTERFACE.Pack_Params();
                        p.count = mBulkData.Count;
                        p.currentbookmark = mBulkData.CurrentBookmark;
                        p.nbolts = mBulkData.NBolts;
                        p.boltNo1st = mBulkData.BoltNo1st;
                        infodata = p.ToBytes();
                    }
                    break;
            }
        }
        #endregion

    }
}
