using FLY.OBJComponents.Common;
using FLY.OBJComponents.IService;
using FLY.Thick.RemoteHistory;
using FObjBase;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Threading;

namespace FLY.OBJComponents.Server
{

    public class Buffer<T> : IBufferAdd<T>
    {
        public List<T> list = new List<T>();
        #region property

        public int NewestID { get; set; } = -1;
        public int Count { get; private set; } = 0;

        /// <summary>
        /// 总容量,当总数量 大于等于 总容量的 100%, 前面的10%数据会被删除
        /// </summary>
        public int Capacity { get; set; }
        #endregion
        public event NotifyBufferChangedEventHandler<T> BufferChanged;
        public event PropertyChangedEventHandler PropertyChanged;
        

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filepath">数据存储路径, null 不保存</param>
        /// <param name="saveInterval">数据保存周期时间 单位:分钟</param>
        /// <param name="capacity">数据总容量</param>
        public Buffer(int capacity = 1000)
        {
            Capacity = capacity;
        }


        public int GetID(int idx)
        {
            int offset = (NewestID - (list.Count() - 1));
            return offset + idx;
        }
        public int GetIndex(int id)
        {
            int offset = (NewestID - (list.Count() - 1));

            return id - offset;
        }
        public void Add(T t)
        {
            list.Add(t);

            if (list.Count() > Capacity)
            {
                list.RemoveRange(0, Capacity / 10);
            }
            
            NewestID++;
            Count = list.Count();



            BufferChanged?.Invoke(this,
                new NotifyBufferChangedEventArgs<T>()
                {
                    Action = NotifyBufferChangedAction.Add,
                    Items = new T[] { t },
                    EndingID = NewestID
                });
        }
        public void AddRange(IEnumerable<T> array)
        {
            list.AddRange(array);

            if (list.Count() > Capacity)
            {
                list.RemoveRange(0, Capacity / 10);
            }
            
            NewestID += array.Count();
            Count = list.Count();

            BufferChanged?.Invoke(this,
                new NotifyBufferChangedEventArgs<T>()
                {
                    Action = NotifyBufferChangedAction.Add,
                    Items = array,
                    EndingID = NewestID
                });
        }
        public override string ToString()
        {
            return "{NewestID:" + NewestID.ToString() + ", " + "Count:" + Count.ToString() + "}";
        }
        public void Replace(int id, T t)
        {
            int idx = GetIndex(id);
            if (idx < 0 || idx >= list.Count())
                return;
            list[idx] = t;
            BufferChanged?.Invoke(this,
                new NotifyBufferChangedEventArgs<T>()
                {
                    Action = NotifyBufferChangedAction.Replace,
                    Items = new T[] { t },
                    EndingID = id
                });
        }
        public void Remove(int id)
        {
            int idx = GetIndex(id);
            if (idx < 0 || idx >= list.Count())
                return;
            T t = list[idx];
            list.RemoveAt(idx);
            Count--;

            BufferChanged?.Invoke(this,
                new NotifyBufferChangedEventArgs<T>()
                {
                    Action = NotifyBufferChangedAction.Remove,
                    EndingID = id,
                    Items = new T[] { t }
                });
        }
        public void Reset()
        {
            list.Clear();
            NewestID = -1;
            Count = 0;
            BufferChanged?.Invoke(this,
                new NotifyBufferChangedEventArgs<T>()
                {
                    Action = NotifyBufferChangedAction.Reset
                });
        }

        /// <summary>
        /// 获取指定位置的N个数据
        /// </summary>
        /// <param name="last_id">最后的ID</param>
        /// <param name="count">数量</param>
        /// <param name="asyncCB">回调</param>
        /// <param name="asyncContext">回调里面的上下文</param>
        public void GetRecord(int last_id, int count, AsyncCBHandler asyncCB, object asyncContext)
        {
            if (list.Count() == 0)
            {
                asyncCB(asyncContext, new GetRecordReponse<T>()
                {
                    LastID = 0,
                    Items = null
                });
                return;
            }

            int firstID = last_id - count + 1;
            int lastID = last_id;

            int rFirstID = NewestID - list.Count() + 1;
            int rLastID = NewestID;

            //以 rFirstID 为偏移量
            int offset = -rFirstID;
            firstID += offset;
            lastID += offset;
            rLastID += offset;
            rFirstID = 0;


            //返回交集
            if (lastID < 0)//在前面
            {
                //没有数据
                asyncCB(asyncContext, new GetRecordReponse<T>()
                {
                    LastID = 0,
                    Items = null
                });
                return;
            }
            else if (firstID > rLastID)//在后面
            {
                //没有数据
                asyncCB(asyncContext, new GetRecordReponse<T>()
                {
                    LastID = 0,
                    Items = null
                });
                return;
            }
            else
            {
                if (firstID < 0)
                    firstID = 0;
                if (lastID > rLastID)
                    lastID = rLastID;
                int cnt = lastID - firstID + 1;
                T[] items = new T[cnt];
                for (int i = 0; i < cnt; i++)
                    items[i] = list[firstID + i];

                asyncCB(asyncContext, new GetRecordReponse<T>()
                {
                    LastID = lastID - offset,
                    Items = items
                });
            }
        }

        /// <summary>
        /// 获取最新的N个数据
        /// </summary>
        /// <param name="count">数量</param>
        /// <param name="asyncCB">回调</param>
        /// <param name="asyncContext">回调里面的上下文</param>
        public void GetRecord(int count, AsyncCBHandler asyncCB, object asyncContext)
        {
            GetRecord(NewestID, count, asyncCB, asyncContext);
        }
    }
}