using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using FObjBase;
using static FLY.Thick.BulkDataModule.BulkDataService;
using System.Collections.Specialized;

namespace FLY.Thick.BulkDataModule
{


    /// <summary>
    /// 推送服务，(AsyncState,param) 作为一个对，不能存在 两个一样的(AsyncState,param)。 它只会推送一次
    /// </summary>
    public interface IBulkDataService : INotifyPropertyChanged
    {
        /// <summary>
        /// 获取一幅数据， 默认带推送
        /// 参数 Pack_CallGetFrameDataParam
        /// 回复 Pack_CallGetFrameDataReturn
        /// </summary>
        /// <param name="param"></param>
        /// <param name="AsyncDelegate"></param>
        /// <param name="AsyncState"></param>
        void GetFrameData(
            BULKDATA_OBJ_INTERFACE.Pack_CallGetFrameDataParam param, AsyncCBHandler AsyncDelegate, object AsyncState);

        /// <summary>
        /// 关闭 扫描图 推送
        /// </summary>
        /// <param name="param"></param>
        /// <param name="AsyncState"></param>
        void ClosePushFrameData(
            BULKDATA_OBJ_INTERFACE.Pack_CallClosePushFrameData param, object AsyncState);

        /// <summary>
        /// 获取纵向趋势图，默认带推送
        /// </summary>
        /// <param name="param"></param>
        /// <param name="AsyncDelegate"></param>
        /// <param name="AsyncState"></param>
        void GetTrendData(
            BULKDATA_OBJ_INTERFACE.Pack_CallGetTrendDataParam param, AsyncCBHandler AsyncDelegate, object AsyncState);
        /// <summary>
        /// 关闭 纵向趋势图 推送
        /// </summary>
        /// <param name="param"></param>
        /// <param name="AsyncState"></param>
        void ClosePushTrendData(
            BULKDATA_OBJ_INTERFACE.Pack_CallClosePushTrendData param, object AsyncState);

        /// <summary>
        /// 注册新数据推送
        /// </summary>
        /// <param name="param"></param>
        /// <param name="AsyncDelegate"></param>
        /// <param name="AsyncState"></param>
        void PushNewFrameData(
            BULKDATA_OBJ_INTERFACE.Pack_CallPushNewFrameDataParam param, AsyncCBHandler AsyncDelegate, object AsyncState);

        /// <summary>
        /// 关闭 新数据推送
        /// </summary>
        /// <param name="param"></param>
        /// <param name="AsyncState"></param>
        void ClosePushNewFrameData(
            BULKDATA_OBJ_INTERFACE.Pack_CallClosePushNewFrameData param, object AsyncState);


        /// <summary>
        /// 获取一幅数据， 默认带推送
        /// 参数 Pack_CallGetFrameDataMixRequest
        /// 回复 Pack_CallGetFrameDataMixReponse
        /// </summary>
        /// <param name="param"></param>
        /// <param name="AsyncDelegate"></param>
        /// <param name="AsyncState"></param>
        void GetFrameDataMix(
            Pack_CallGetFrameDataMixRequest param, AsyncCBHandler AsyncDelegate, object AsyncState);

        /// <summary>
        /// 关闭 扫描图 推送
        /// </summary>
        /// <param name="param"></param>
        /// <param name="AsyncState"></param>
        void ClosePushFrameDataMix(
            Pack_CallClosePushFrameDataMixRequest param, object AsyncState);



        /// <summary>
        /// 清空缓存区
        /// </summary>
        void Clear();

        /// <summary>
        /// 只要 AsyncState 满足 match 的都要删除
        /// </summary>
        /// <param name="match">AsyncState 规则</param>
        void ClosePush(Predicate<object> match);

        /// <summary>
        /// 准备好，只有在 IsReady=true ，发送的命令才能执行，才能推送
        /// </summary>
        bool IsConnected { get; }

        /// <summary>
        /// 缓冲区数据
        /// </summary>
        List<FR_DATA> Datas { get; }
        /// <summary>
        /// 数量
        /// </summary>
        int Count { get; }

        /// <summary>
        /// 分区数
        /// </summary>
        int NBolts { get; }

        /// <summary>
        /// 第1分区号
        /// </summary>
        int BoltNo1st { get; }
        /// <summary>
        /// 最新的bookmark
        /// </summary>
        int CurrentBookmark { get; }

        //
        // 摘要:
        //     在添加、移除、更改或者在刷新整个列表时发生。
        event NotifyDatasChangedEventHandler DatasChanged;

    }

    
    public class NotifyDatasChangedEventArgs : EventArgs
    {
        public NotifyDatasChangedAction Action;
        public int NewStartingIndex;
        public List<FR_DATA> Items;
    }
    public enum NotifyDatasChangedAction
    {
        Add,
        Replace,
        Reset
    }
    public delegate void NotifyDatasChangedEventHandler(object sender, NotifyDatasChangedEventArgs e);

    /// <summary>
    /// 作为服务器端 添加，改变 数据
    /// </summary>
    public interface IBulkDataServiceAdd 
    {
        /// <summary>
        /// 分区数
        /// </summary>
        int NBolts { get; set; }
        /// <summary>
        /// 第1分区号
        /// </summary>
        int BoltNo1st { get; set; }
        /// <summary>
        /// 初始化推送
        /// </summary>
        void InitPush();
        /// <summary>
        /// 添加空数据
        /// </summary>
        /// <returns></returns>
        int AddEmply();
        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="buf"></param>
        /// <param name="type"></param>
        /// <param name="dt"></param>
        /// <returns></returns>
        int Add(int[] buf, FR_DATA_TYPE type, DateTime dt);
        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="buf"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        int Add(int[] buf, FR_DATA_TYPE type);

        /// <summary>
        /// 改变数据
        /// </summary>
        /// <param name="bm"></param>
        /// <param name="start_boltIndex"></param>
        /// <param name="buf"></param>
        /// <param name="type"></param>
        /// <param name="time"></param>
        /// <returns></returns>
        bool Change(int bm, int start_boltIndex, int[] buf, FR_DATA_TYPE type, DateTime time);
        /// <summary>
        /// 改变数据
        /// </summary>
        /// <param name="bm"></param>
        /// <param name="start_boltIndex"></param>
        /// <param name="buf"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        bool Change(int bm, int start_boltIndex, int[] buf, FR_DATA_TYPE type);
        /// <summary>
        /// 改变数据为空
        /// </summary>
        /// <param name="bm"></param>
        /// <returns></returns>
        bool ChangeEmply(int bm);
        /// <summary>
        /// 改变最新幅数据为空
        /// </summary>
        /// <returns></returns>
        bool ChangeEmply();
        
        /// <summary>
        /// 保存
        /// </summary>
        void Save();
    }


    /// <summary>
    /// 
    /// </summary>
    public class Pack_CallGetFrameDataMixRequest : Pack_CallClosePushFrameDataMixRequest
    {
        /// <summary>
        /// 当数据变化时，是否需要推送
        /// </summary>
        public bool NeedPush;

        #region IPack 成员

        /// <summary>
        /// 转换为 17个字节
        /// </summary>
        /// <returns></returns>
        public override byte[] ToBytes()
        {
            List<byte> buf = new List<byte>();
            buf.AddRange(base.ToBytes());
            buf.AddRange(BitConverter.GetBytes(NeedPush));
            return buf.ToArray();
        }
        /// <summary>
        /// 17个字节 类型转换
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public override bool TryParse(byte[] value)
        {
            if (!base.TryParse(value))
                return false;
            int index = 16;
            int cnt = 1;
            int idx = index;
            if (value.Length < cnt+index)
                return false;
            
            NeedPush = BitConverter.ToBoolean(value, idx);
            idx += 1;
            return true;
        }

        #endregion
    }
    /// <summary>
    /// 
    /// </summary>
    public class Pack_CallGetFrameDataMixReponse : Pack_CallGetFrameDataMixRequest
    {
        /// <summary>
        /// 结果对应的 bookmark
        /// </summary>
        public int bookmark = -1;
        /// <summary>
        /// 结果对应的 实际结束时间
        /// </summary>
        public DateTime dt = DateTime.MinValue;
        /// <summary>
        /// 结果对应的 实际开始时间
        /// </summary>
        public DateTime act_startDt = DateTime.MinValue;
        /// <summary>
        /// 开始分区index
        /// </summary>
        public int fromBoltIndex = 0;
        /// <summary>
        /// 结束分区index
        /// </summary>
        public int toBoltIndex = 0;
        /// <summary>
        /// 结果.数据是否有效
        /// </summary>
        public FR_DATA_TYPE type = FR_DATA_TYPE.INVALID;
        /// <summary>
        /// 结果， 当needPush=true, 以后推送时，只发送变化了的数据
        /// </summary>
        public FrameDataCell[] result = null;

        #region IPack 成员

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override byte[] ToBytes()
        {
            List<byte> buf = new List<byte>();
            buf.AddRange(base.ToBytes());//17
            
            buf.AddRange(BitConverter.GetBytes(bookmark));//4
            buf.AddRange(BitConverter.GetBytes(dt.Ticks));//8
            buf.AddRange(BitConverter.GetBytes(act_startDt.Ticks));//8
            buf.AddRange(BitConverter.GetBytes(fromBoltIndex));//4
            buf.AddRange(BitConverter.GetBytes(toBoltIndex));//4
            buf.Add((byte)type);//1
            if (result != null)
            {
                buf.AddRange(BitConverter.GetBytes((int)result.Length));//4
                foreach (FrameDataCell dat in result)
                    buf.AddRange(dat.ToBytes());
            }
            else
            {
                buf.AddRange(BitConverter.GetBytes((int)0));//4
            }
            return buf.ToArray();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public override bool TryParse(byte[] value)
        {
            if (!base.TryParse(value))
                return false;
            int index = 17;
            int cnt = 4 + 8 + 8 + 4 + 4 + 1 + 4;
            if (value.Length < cnt+index)
                return false;

            int idx = index;
            
            bookmark = BitConverter.ToInt32(value, idx);
            idx += 4;
            try
            {
                dt = new DateTime(BitConverter.ToInt64(value, idx));
            }
            catch
            {
                return false;
            }
            idx += 8;

            try
            {
                act_startDt = new DateTime(BitConverter.ToInt64(value, idx));
            }
            catch
            {
                return false;
            }
            idx += 8;
            fromBoltIndex = BitConverter.ToInt32(value, idx);
            idx += 4;
            toBoltIndex = BitConverter.ToInt32(value, idx);
            idx += 4;
            type = (FR_DATA_TYPE)value[idx];
            idx += 1;

            int length = BitConverter.ToInt32(value, idx);
            idx += 4;
            
            if (length > 0)
            {
                cnt += length * 4;
                if (value.Length < cnt + index)
                    return false;

                result = new FrameDataCell[length];
                for (int i = 0; i < length; i++)
                {
                    result[i] = new FrameDataCell();
                    result[i].TryParse(value, idx);
                    idx += 8;
                }
            }
            else
            {
                result = null;
            }
            return true;
        }

        #endregion
    }
    
    /// <summary>
    /// 
    /// </summary>
    public class Pack_CallClosePushFrameDataMixRequest : IPack
    {
        /// <summary>
        /// 标记, 当bm&gt;0 为bookmark，当bm &lt;=0 为往前面数
        /// </summary>
        public int bm;

        /// <summary>
        /// 混合数
        /// </summary>
        public int mix;

        /// <summary>
        /// 混合数据，只能从 start_dt 开始 
        /// </summary>
        public DateTime start_dt;

        #region IPack 成员
        /// <summary>
        /// 转换为 16个字节
        /// </summary>
        /// <returns></returns>
        public virtual byte[] ToBytes()
        {
            List<byte> buf = new List<byte>();
            buf.AddRange(BitConverter.GetBytes(bm));
            buf.AddRange(BitConverter.GetBytes(mix));
            buf.AddRange(BitConverter.GetBytes(start_dt.Ticks));
            return buf.ToArray();
        }
        /// <summary>
        /// 16个字节 类型转换
        /// </summary>
        /// <returns></returns>
        public virtual bool TryParse(byte[] value)
        {
            int count = 4+4+8;
            if (value.Length < count)
                return false;

            int idx = 0;
            bm = BitConverter.ToInt32(value, idx);
            idx += 4;
            mix = BitConverter.ToInt32(value, idx);
            idx += 4;

            try
            {
                start_dt = new DateTime(BitConverter.ToInt64(value, idx));
            }
            catch
            {
                start_dt = DateTime.MinValue;
            }
            idx += 8;
            return true;
        }

        #endregion
        /// <summary>
        /// 参数是否一样
        /// </summary>
        /// <param name="dest"></param>
        /// <returns></returns>
        public bool IsSame(Pack_CallClosePushFrameDataMixRequest dest)
        {
            if ((bm == dest.bm) && (mix == dest.mix) && (start_dt == dest.start_dt))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }

}
