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

namespace FLY.Thick.BulkDataModule
{
    /// <summary>
    /// 功能 
    /// 1. 获取横向扫描图，变化时推送变化量
    /// 3. 获取指定分区范围的纵向趋势图，变化时推送变化量
    /// 5. 获取 幅信息(基本没用)
    /// 6. 删去全部数据
    /// </summary>
    public class BULKDATA_OBJ_INTERFACE
    {
        public const UInt32 ID = 0x003C0001;
        
        #region Pack
        public class Pack_CallPushNewFrameDataParam : IPack 
        {
            public int mix;//混合数

            #region IPack 成员

            public virtual byte[] ToBytes()
            {
                List<byte> buf = new List<byte>();
                buf.AddRange(BitConverter.GetBytes(mix));
                return buf.ToArray();
            }

            public virtual bool TryParse(byte[] value)
            {
                int count = 4;
                if (value.Length < count)
                    return false;

                int idx = 0;
                mix = BitConverter.ToInt32(value, idx);
                idx += 4;
                return true;
            }

            #endregion
        }
        public class Pack_CallPushNewFrameDataReturn : Pack_CallPushNewFrameDataParam
        {
            //输出
            public int bookmark = -1;//结果对应的 bookmark
            public DateTime dt = DateTime.MinValue;//结果对应的 时间
            public FR_DATA_TYPE type = FR_DATA_TYPE.INVALID;//结果.数据是否有效
            public int[] result = null;//结果， 当needPush=true, 以后推送时，只发送变化了的数据

            #region IPack 成员

            public override byte[] ToBytes()
            {
                List<byte> buf = new List<byte>();
                buf.AddRange(BitConverter.GetBytes(mix));
                buf.AddRange(BitConverter.GetBytes(bookmark));

                buf.AddRange(BitConverter.GetBytes(dt.Ticks));
                buf.Add((byte)type);
                
                int len=0;

                if (result != null)
                    len = result.Length;
                
                buf.AddRange(BitConverter.GetBytes(len));
                
                if(len>0)
                {
                    foreach (int dat in result)
                        buf.AddRange(BitConverter.GetBytes(dat));
                }
                
                return buf.ToArray();
            }

            public override bool TryParse(byte[] value)
            {
                int count = 4 + 4 + 8 + 1 + 4;
                if (value.Length < count)
                    return false;

                int idx = 0;
                mix = BitConverter.ToInt32(value, idx);
                idx += 4;
                bookmark = BitConverter.ToInt32(value, idx);
                idx += 4;
                dt = new DateTime(BitConverter.ToInt64(value, idx));
                idx += 8;
                type = (FR_DATA_TYPE)value[idx];
                idx += 1;
                int length = BitConverter.ToInt32(value, idx);
                idx += 4;

                count += length * 4;
                if (value.Length < count)
                    return false;

                if (length > 0)
                {
                    result = new int[length];
                    for (int i = 0; i < length; i++)
                    {
                        result[i] = BitConverter.ToInt32(value, idx);
                        idx += 4;
                    }
                }
                else
                {
                    result = null;
                }
                return true;
            }

            #endregion
        }
        public class Pack_CallClosePushNewFrameData : Pack_CallPushNewFrameDataParam
        {

        }


        public class Pack_CallGetFrameDataParam : Pack_CallClosePushFrameData
        {
            public bool NeedPush;//当数据变化时，是否需要推送

            #region IPack 成员


            public override byte[] ToBytes()
            {
                List<byte> buf = new List<byte>();
                buf.AddRange(BitConverter.GetBytes(NeedPush));
                buf.AddRange(BitConverter.GetBytes(bm));
                buf.AddRange(BitConverter.GetBytes(mix));
                return buf.ToArray();
            }

            public override bool TryParse(byte[] value)
            {
                if (value == null)
                    return false;
                //TODO
                int count = 9;
                if (value.Length < count)
                    return false;

                int idx = 0;
                NeedPush = BitConverter.ToBoolean(value, idx);
                idx += 1;
                bm = BitConverter.ToInt32(value, idx);
                idx += 4;
                mix = BitConverter.ToInt32(value, idx);
                idx += 4;
                return true;
            }

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

            #region IPack 成员

            public override byte[] ToBytes()
            {
                List<byte> buf = new List<byte>();
                buf.AddRange(BitConverter.GetBytes(NeedPush));//1
                buf.AddRange(BitConverter.GetBytes(bm));//2
                buf.AddRange(BitConverter.GetBytes(mix));//3

                buf.AddRange(BitConverter.GetBytes(bookmark));//4
                buf.AddRange(BitConverter.GetBytes(dt.Ticks));//5
                buf.AddRange(BitConverter.GetBytes(fromBoltIndex));//6
                buf.AddRange(BitConverter.GetBytes(toBoltIndex));//7
                buf.Add((byte)type);//8
                if (result != null)
                {
                    buf.AddRange(BitConverter.GetBytes((int)result.Length));//9
                    foreach (int dat in result)
                        buf.AddRange(BitConverter.GetBytes(dat));
                }
                else
                {
                    buf.AddRange(BitConverter.GetBytes((int)0));//9
                }
                return buf.ToArray();
            }

            public override bool TryParse(byte[] value)
            {
                int count = 1 + 4 * 2+ 4 + 8+ 4*2 + 1 + 4;
                if (value.Length < count)
                    return false;

                int idx = 0;
                NeedPush = BitConverter.ToBoolean(value, idx);//1
                idx++;

                bm = BitConverter.ToInt32(value, idx);//2
                idx += 4;
                mix = BitConverter.ToInt32(value, idx);//3
                idx += 4;
                bookmark = BitConverter.ToInt32(value, idx);//4
                idx += 4;
                dt = new DateTime(BitConverter.ToInt64(value, idx));//5
                idx += 8;
                fromBoltIndex = BitConverter.ToInt32(value, idx);//6
                idx += 4;
                toBoltIndex = BitConverter.ToInt32(value, idx);//7
                idx += 4;
                type = (FR_DATA_TYPE)value[idx];//8
                idx += 1;
                int length = BitConverter.ToInt32(value, idx);//9
                idx += 4;

                count += length * 4;
                if (value.Length < count)
                    return false;

                if (length > 0)
                {
                    result = new int[length];
                    for (int i = 0; i < length; i++)
                    {
                        result[i] = BitConverter.ToInt32(value, idx);
                        idx += 4;
                    }
                }
                else
                {
                    result = null;
                }
                return true;
            }

            #endregion
        }
        public class Pack_CallClosePushFrameData : IPack
        {
            public int bm;//标记, 当bm>0 为bookmark，当bm <=0 为往前面数
            public int mix;//混合数

            #region IPack 成员

            public virtual byte[] ToBytes()
            {
                List<byte> buf = new List<byte>();
                buf.AddRange(BitConverter.GetBytes(bm));
                buf.AddRange(BitConverter.GetBytes(mix));
                return buf.ToArray();
            }

            public virtual bool TryParse(byte[] value)
            {
                int count = 8;
                if (value.Length < count)
                    return false;

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

            #endregion
        }

        public class Pack_CallGetTrendDataParam : Pack_CallClosePushTrendData
        {
            public bool NeedPush;//当数据变化时，是否需要推送
            public int len;//获取的长度

            #region IPack 成员

            public override byte[] ToBytes()
            {
                List<byte> buf = new List<byte>();
                buf.AddRange(BitConverter.GetBytes(NeedPush));
                buf.AddRange(BitConverter.GetBytes(len));
                buf.AddRange(BitConverter.GetBytes(mix));
                buf.AddRange(BitConverter.GetBytes(fromBoltNo));
                buf.AddRange(BitConverter.GetBytes(toBoltNo));
                return buf.ToArray();
            }

            public override bool TryParse(byte[] value)
            {
                int count = 1+4*4;
                if (value.Length < count)
                    return false;

                int idx = 0;
                NeedPush = BitConverter.ToBoolean(value, idx);
                idx++;
                len = BitConverter.ToInt32(value, idx);
                idx += 4;
                mix = BitConverter.ToInt32(value, idx);
                idx += 4;
                fromBoltNo = BitConverter.ToInt32(value, idx);
                idx += 4;
                toBoltNo = BitConverter.ToInt32(value, idx);
                idx += 4;
                return true;
            }

            #endregion
        }
        public class Pack_CallGetTrendDataReturn : Pack_CallGetTrendDataParam
        {
            //输出
          
            /// <summary>
            /// 结果修改的位置; 1 在上一次数据最后一位的后面添加; 0 在上一次数据最后一位 开始修改;
            /// </summary>
            public int edit_position = 1;
            public TrendDataCell[] result = null;//结果,当 长度=0，数据被清空！！


            #region IPack 成员

            public override byte[] ToBytes()
            {
                List<byte> buf = new List<byte>();
                buf.AddRange(BitConverter.GetBytes(NeedPush));
                buf.AddRange(BitConverter.GetBytes(len));
                buf.AddRange(BitConverter.GetBytes(mix));
                buf.AddRange(BitConverter.GetBytes(fromBoltNo));
                buf.AddRange(BitConverter.GetBytes(toBoltNo));

                buf.AddRange(BitConverter.GetBytes(edit_position));
                if (result != null)
                {
                    buf.AddRange(BitConverter.GetBytes((int)result.Length));

                    foreach (TrendDataCell dat in result)
                        buf.AddRange(dat.ToBytes());
                }
                else
                {
                    buf.AddRange(BitConverter.GetBytes((int)0));
                }

                return buf.ToArray();
            }

            public override bool TryParse(byte[] value)
            {
                int count = 1 + 4 * 6;
                if (value.Length < count)
                    return false;

                int idx = 0;
                NeedPush = BitConverter.ToBoolean(value, idx);
                idx++;
                len = BitConverter.ToInt32(value, idx);
                idx += 4;
                mix = BitConverter.ToInt32(value, idx);
                idx += 4;
                fromBoltNo = BitConverter.ToInt32(value, idx);
                idx += 4;
                toBoltNo = BitConverter.ToInt32(value, idx);
                idx += 4;
                edit_position = BitConverter.ToInt32(value, idx);
                idx += 4;

                int length = BitConverter.ToInt32(value, idx);
                idx += 4;

                count += length * 20;
                if (value.Length < count)
                    return false;


                if (length > 0)
                {
                    result = new TrendDataCell[length];

                    for (int i = 0; i < length; i++)
                    {
                        result[i] = new TrendDataCell();
                        if (!result[i].TryParse(value, idx))
                        {
                            return false;
                        }
                        idx += 20;
                    }
                }
                else
                {
                    result = null;
                }
                return true;
            }

            #endregion
        }
        public class Pack_CallClosePushTrendData : IPack
        {
            public int mix;//混合数
            public int fromBoltNo;//开始分区index
            public int toBoltNo;//结束分区index

            #region IPack 成员

            public virtual byte[] ToBytes()
            {
                List<byte> buf = new List<byte>();
                buf.AddRange(BitConverter.GetBytes(mix));
                buf.AddRange(BitConverter.GetBytes(fromBoltNo));
                buf.AddRange(BitConverter.GetBytes(toBoltNo));
                return buf.ToArray();
            }

            public virtual bool TryParse(byte[] value)
            {
                int count = 3 * 4;
                if (value.Length < count)
                    return false;

                int idx = 0;
                mix = BitConverter.ToInt32(value, idx);
                idx += 4;
                fromBoltNo = BitConverter.ToInt32(value, idx);
                idx += 4;
                toBoltNo = BitConverter.ToInt32(value, idx);
                idx += 4;
                return true;
            }

            #endregion
        }

        public class Pack_CallGetListReponse : IPack2
        {
            public List<FR_DATA> list = new List<FR_DATA>();
            #region IPack 成员

            public virtual byte[] ToBytes()
            {
                List<byte> buf = new List<byte>();

                buf.AddRange(BitConverter.GetBytes(list.Count));

                for (int i = 0; i < list.Count; i++)
                {
                    buf.AddRange(list[i].ToBytes());
                }

                return buf.ToArray();
            }

            public bool TryParse(byte[] value)
            {
                int cnt;
                return TryParse(value, 0, out cnt);
            }

            public bool TryParse(byte[] value, int index, out int cnt)
            {
                cnt = 4;
                if (value.Length < (index + cnt))
                    return false;
                int idx = index;

                int len = BitConverter.ToInt32(value, idx);
                idx += 4;
                list.Clear();

                if (len <= 0)
                {
                    return true;
                }

                for (int i = 0; i < len; i++)
                {
                    int c;
                    FR_DATA t = new FR_DATA();
                    if (!t.TryParse(value, idx, out c))
                        return false;
                    list.Add(t);
                    idx += c;
                    cnt += c;
                }
                return true;
            }

            #endregion
        }
        public class Pack_PushChanged : IPack2
        {
            public NotifyDatasChangedAction Action;
            public FR_DATA data;

            #region IPack 成员

            public virtual byte[] ToBytes()
            {
                List<byte> buf = new List<byte>();
                buf.AddRange(BitConverter.GetBytes((int)Action));
                if (data == null)
                    data = new FR_DATA();
                buf.AddRange(data.ToBytes());
                
                return buf.ToArray();
            }

            public bool TryParse(byte[] value)
            {
                int cnt;
                return TryParse(value, 0, out cnt);
            }

            public bool TryParse(byte[] value, int index, out int cnt)
            {
                cnt = 4;
                if (value.Length < (index + cnt))
                    return false;
                int idx = index;

                Action = (NotifyDatasChangedAction)BitConverter.ToInt32(value, idx);
                idx += 4;
                int c;
                FR_DATA t = new FR_DATA();
                if (!t.TryParse(value, idx, out c))
                    return false;
                idx += c;
                cnt += c;
                data = t;
                return true;
            }

            #endregion
        }

        public class Pack_Params
        {
            public int count;
            public int currentbookmark;
            public int nbolts;
            public int boltNo1st;

            #region IPack实现
            public byte[] ToBytes()
            {
                List<byte> buf = new List<byte>();

                buf.AddRange(BitConverter.GetBytes(count));
                buf.AddRange(BitConverter.GetBytes(currentbookmark));
                buf.AddRange(BitConverter.GetBytes(nbolts));
                buf.AddRange(BitConverter.GetBytes(boltNo1st));
                return buf.ToArray();
            }

            public bool TryParse(byte[] value)
            {
                int cnt = 4*4;
                if (value.Length < cnt)
                    return false;

                int idx = 0;
                count = BitConverter.ToInt32(value, idx);
                idx += 4;
                currentbookmark = BitConverter.ToInt32(value, idx);
                idx += 4;
                nbolts = BitConverter.ToInt32(value, idx);
                idx += 4;
                boltNo1st = BitConverter.ToInt32(value, idx);
                idx += 4;
                return true;
            }
            #endregion
        }
        #endregion

        #region GET/SET/CALL/PUSH
        #region GET
        /// <summary>
        /// Pack_Params
        /// </summary>
        public const UInt16 GET_PARAMS = 15;
        

        #endregion
        #region CALL
        /// <summary>
        /// Pack_CallGetFrameDataParam
        /// Pack_CallGetFrameDataReturn
        /// </summary>
        public const UInt16 CALL_GET_FRAMEDATA = 1;//横向


        /// <summary>
        /// Pack_CallClosePushFrameData
        /// </summary>
        public const UInt16 CALL_CLOSE_PUSH_FRAMEDATA = 2;//关闭推送


        /// <summary>
        /// param:Pack_CallGetTrendDataParam;
        /// return:Pack_CallGetTrendDataReturn
        /// </summary>
        public const UInt16 CALL_GET_TRENDDATA = 3;//获取指定分区范围的纵向趋势图

        /// <summary>
        /// Pack_CallClosePushTrendData
        /// </summary>
        public const UInt16 CALL_CLOSE_PUSH_TRENDDATA = 4;//关闭推送

        
        /// <summary>
        /// no pack
        /// </summary>
        public const UInt16 CALL_CLEAR = 6;//清空


        /// <summary>
        /// Pack_CallPushNewFrameDataParam
        /// Pack_CallPushNewFrameDataReturn
        /// </summary>
        public const UInt16 CALL_PUSH_NEWFRAMEDATA = 7;//横向


        /// <summary>
        /// Pack_CallClosePushNewFrameData
        /// </summary>
        public const UInt16 CALL_CLOSE_PUSH_NEWFRAMEDATA = 8;//关闭推送


        /// <summary>
        /// Pack_CallGetFrameDataMixRequest
        /// Pack_CallGetFrameDataMixReponse
        /// </summary>
        public const UInt16 CALL_GET_FRAMEDATAMIX = 9;//横向


        /// <summary>
        /// Pack_CallClosePushFrameDataMixRequest
        /// </summary>
        public const UInt16 CALL_CLOSE_PUSH_FRAMEDATAMIX = 10;//关闭推送

        /// <summary>
        /// 获取最新的10幅数据
        /// Reponse: Pack_CallGetListReponse &lt; FR_DATA &gt;
        /// </summary>
        public const UInt16 CALL_GET_LIST_NEW_10 = 11;
        /// <summary>
        /// 获取最新的10幅数据其它数据
        /// Reponse: Pack_CallGetListReponse &lt; FR_DATA &gt;
        /// </summary>
        public const UInt16 CALL_GET_LIST_OTHER = 12;
        #endregion
        #region PUSH
        //永远没有push，用callfunction 推送回去

        /// <summary>
        /// Pack_Params
        /// </summary>
        public const UInt16 PUSH_PARAMS = 15;
        /// <summary>
        /// Reponse: FR_DATA
        /// </summary>
        public const UInt16 PUSH_CHANGED = 16;
        #endregion
        #endregion
    }  
}
