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

namespace FLY.Thick.RemoteHistory
{
    public class BufferServiceClient<T> : FObj, IBuffer<T>
        where T : IPack2, new()
    {
        #region 延时推送 MARKNO
        const int MARKNO_SET_PARAMS = 1;
        #endregion

        IFConn mConn;
        UInt32 mServerID;

        #region IBuffer<T>
        private int size = 400;
        public int Size
        {
            get { return size; }
            set
            {
                if (value < 100)
                    value = 100;
                if (size != value)
                {
                    size = value;
                    NotifyPropertyChanged("Size");
                }
            }
        }
        private List<T> record = new List<T>();
        /// <summary>
        /// 每次配料记录
        /// </summary>
        public List<T> Record
        {
            get
            {
                return record;
            }
        }



        public event BufferChangedEventHandler RecordChanged;
        void NotifyRecordChanged(bool isAdd, int cnt)
        {
            if (RecordChanged != null)
            {
                RecordChanged.Invoke(Record, new BufferChangedEventArgs(isAdd, cnt));
            }
        }
        #endregion


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


        public ObservableCollection<T> GetObservableCollection()
        {
            ObservableCollection<T> datas = new ObservableCollection<T>(Record);
            RecordChanged += (s, e) =>
            {
                if (e.IsAdd)
                {
                    for (int i = 0; i < e.Cnt; i++)
                    {
                        int index = Record.Count - e.Cnt + i;
                        datas.Add(Record[index]);
                    }
                    while (datas.Count > Size)
                        datas.RemoveAt(0);
                }
                else
                {
                    datas.Clear();
                    for (int i = 0; i < e.Cnt; i++)
                    {
                        datas.Add(Record[i]);
                    }
                }
            };
            return datas;
        }


        private void BufferServiceClient_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (
                (e.PropertyName == "Size"))
            {
                FObjBase.PollModule.Current.Poll_JustOnce(
                    new PollModule.PollHandler(delegate()
                    {

                        BUFFER_OBJ_INTERFACE.Pack_Params p = new BUFFER_OBJ_INTERFACE.Pack_Params();
                        p.size = Size;
                        CurrObjSys.PushObjInfoEx(
                            this, BUFFER_OBJ_INTERFACE.SET_PARAMS,
                            p.ToBytes());
                    }), this, MARKNO_SET_PARAMS);
            }
        }

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

                CurrObjSys.SenseConfigEx(
                    mConn, mServerID, ID,
                    0xffffffff,
                    SENSE_CONFIG.ADD);
            }
        }
        public override void PushGetValue(IFConn from, uint srcid, ushort memid, byte[] infodata)
        {
            switch (memid)
            {
                case BUFFER_OBJ_INTERFACE.GET_LIST:
                    {
                        BUFFER_OBJ_INTERFACE.Pack_List<T> p = new BUFFER_OBJ_INTERFACE.Pack_List<T>();
                        if (!p.TryParse(infodata))
                            return;
                        int cnt = 0;
                        if (p.list != null)
                        {
                            cnt = p.list.Count();
                            if (cnt > Size)
                                cnt = Size;
                        }
                        if (!p.isAdd)//isChanged
                            Record.Clear();

                        if (cnt > 0)
                        {
                            Record.AddRange(p.list);
                            while (Record.Count() > Size)
                            {
                                Record.RemoveAt(0);
                            }
                        }

                        NotifyRecordChanged(p.isAdd, cnt);
                    }
                    break;
                case BUFFER_OBJ_INTERFACE.GET_PARAMS:
                    {
                        BUFFER_OBJ_INTERFACE.Pack_Params p = new BUFFER_OBJ_INTERFACE.Pack_Params();
                        if (!p.TryParse(infodata))
                            return;
                        this.PropertyChanged -= BufferServiceClient_PropertyChanged;
                        Size = p.size;
                        this.PropertyChanged += BufferServiceClient_PropertyChanged;
                    }
                    break;
            }
        }
        public override void PushInfo(IFConn from, uint srcid, ushort infoid, byte[] infodata)
        {
            PushGetValue(from, srcid, infoid, infodata);
        }

        #region INotifyPropertyChanged 成员

        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged(string propertyname)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyname));
            }
        }
        #endregion
    }
}
