using Misc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FlyADBase
{
    /// <summary>
    /// 高级timegrid助手
    /// </summary>
    public class TimeGridAdvHelper
    {
        NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();


        /// <summary>
        /// AD数据池时间间隔为1.28ms, 肯定最少有一个数据 
        /// </summary>
        RList<DataTimeUnit> ADPool = new RList<DataTimeUnit>(60000);

        /// <summary>
        /// pos 数据池, 肯定最少有一个数据
        /// </summary>
        RList<DataTimeUnit> PosPool = new RList<DataTimeUnit>(60000);

        /// <summary>
        /// 输入端口 数据池, 肯定最少有一个数据
        /// </summary>
        RList<DataTimeUnit2> IStatusPool = new RList<DataTimeUnit2>(60000);

        /// <summary>
        /// 上一次查找istatus的序号
        /// </summary>
        int istatus_start_idx = -1;
        /// <summary>
        /// 上一次查找pos的序号
        /// </summary>
        int pos_start_idx = -1;
        void ResetSearch() 
        {
            istatus_start_idx = -1;
            pos_start_idx = -1;
        }
        /// <summary>
        /// 
        /// </summary>
        public void Init()
        {
            Clear();
        }


        /// <summary>
        /// 添加ad数据,且判断数据量是否够触发事件
        /// </summary>
        /// <param name="ads">ad值</param>
        /// <param name="start_dt">开始时间</param>
        /// <param name="ts_ms">每个数据的时间间隔 单位ms</param>
        public void AddAD(int[] ads, DateTime start_dt, double ts_ms)
        {
            //------------------------------------------------------------------------------------------
            //AD数据添加
            for (int i = 0; i < ads.Count(); i++)
            {
                DateTime dt = start_dt + TimeSpan.FromTicks((long)(TimeSpan.TicksPerMillisecond * i * ts_ms));
                ADPool.RAdd(new DataTimeUnit() { data = ads[i], dt = dt });
            }
        }
        /// <summary>
        /// 添加脉冲
        /// </summary>
        /// <param name="pos"></param>
        /// <param name="time"></param>
        public void AddPos(int pos, DateTime time)
        {
            if (PosPool.Count() > 0)
            {
                if (time < PosPool.Last().dt)
                {
                    //异常
                    //把前面的都删除
                    PosPool.Clear();
                }
                else if (time == PosPool.Last().dt)
                {
                    return;
                }
            }
            PosPool.RAdd(new DataTimeUnit() { data = pos, dt = time });
        }

        /// <summary>
        /// 添加输入口状态
        /// </summary>
        /// <param name="istatus"></param>
        /// <param name="pos"></param>
        /// <param name="time"></param>
        public void AddIStatus(UInt16 istatus, int pos, DateTime time)
        {
            if (IStatusPool.Count() > 0)
            {
                if (time < IStatusPool.Last().dt)
                {
                    //异常
                    //把前面的都删除
                    IStatusPool.Clear();
                }
            }

            IStatusPool.RAdd(new DataTimeUnit2() { istatus = istatus, pos = pos, dt = time });

            //也添加到 PosPool
            //AddPos(pos, time);
        }

        /// <summary>
        /// 添加开始位置
        /// </summary>
        /// <param name="pos"></param>
        /// <param name="time"></param>
        public void AddPos_Default(int pos, DateTime time)
        {
            if (PosPool.Count() == 0)
            {
                AddPos(pos, time);
            }
        }
        /// <summary>
        /// 添加开始输入口状态
        /// </summary>
        /// <param name="istatus"></param>
        /// <param name="pos"></param>
        /// <param name="time"></param>
        public void AddIStatus_Default(UInt16 istatus, int pos, DateTime time)
        {
            if (IStatusPool.Count() == 0)
            {
                AddIStatus(istatus, pos, time);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        public void Clear()
        {
            PosPool.Clear();
            ADPool.Clear();
            IStatusPool.Clear();

            ResetSearch();
        }

        /// <summary>
        /// 给定结束时间点,开始grid, 找到pos数据池 对应的开始序号 与 结束序号
        /// </summary>
        /// <param name="start_pos">开始脉冲</param>
        /// <param name="endtime">结束时间点</param>
        /// <param name="start_idx">输出 pos数据池开始序号</param>
        /// <param name="end_idx">输出 pos数据池结束序号</param>
        /// <returns>false 发生在数据池前面, true成功获取</returns>
        bool GetIdxFromPosPool(int start_pos, DateTime endtime, out int start_idx, out int end_idx)
        {
            start_idx = -1;
            end_idx = searchIndex(PosPool, endtime, -1);
            if (end_idx == -1)
            {
                //endtime 发生在过去很久以前
                return false;
            }

            int pos_last = int.MinValue;
            int i_last = -1;
            for (int i = end_idx; i >= 0; i--)
            {

                int pos = PosPool[i].data;

                //if (pos == start_pos)//找到了!!!!
                //{
                //    pos_last = pos;
                //    continue;
                //}

                if (pos_last == int.MinValue)
                {
                    pos_last = pos;
                    i_last = i;
                    continue;
                }

                if (pos_last == pos)
                {
                    continue;
                }

                if (Math.Abs(pos - start_pos) > Math.Abs(pos_last - start_pos))
                {
                    //越找越远,
                    //上一个就是了
                    start_idx = i_last;
                    return true;
                }
                else if (Math.Abs(pos - start_pos) == Math.Abs(pos_last - start_pos))
                {
                    //跨过了
                    start_idx = i_last;
                    return true;
                }

                pos_last = pos;
                i_last = i;
            }
            //找完
            start_idx = 0;
            return true;
        }



        /// <summary>
        /// 根据时间点,获取输入口状态
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        UInt16 GetIStatus(DateTime dt)
        {
            int index = searchIndex(IStatusPool, dt, istatus_start_idx);
            istatus_start_idx = index;

            if (index < 0)
                return 0xffff;
            else
                return (UInt16)IStatusPool[index].istatus;
        }

        /// <summary>
        /// 根据时间点,获取输入口状态
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        UInt16 GetIStatus(DateTime dt, out int index)
        {
            index = searchIndex(IStatusPool, dt, istatus_start_idx);
            istatus_start_idx = index;

            if (index < 0)
                return 0xffff;
            else
                return (UInt16)IStatusPool[index].istatus;
        }


        /// <summary>
        /// 以 [idx,idx+1] 的比例, 给出 time 计算 pos 
        /// </summary>
        /// <param name="time"></param>
        /// <param name="idx"></param>
        /// <returns></returns>
        int GetPos(DateTime time, int idx)
        {
            if (PosPool.Count() < 0)
                return int.MinValue;

            if (PosPool.Count() == 1)
                return PosPool[0].data;

            if (idx < 0)
                idx = 0;

            if (idx >= PosPool.Count()-1)
                idx = PosPool.Count() - 2;

            double d_pos = PosPool[idx].data - PosPool[idx + 1].data;

            TimeSpan ts = PosPool[idx].dt - PosPool[idx + 1].dt;
            double p = d_pos * (time - PosPool[idx + 1].dt).Ticks / ts.Ticks;

            return (int)(p + PosPool[idx + 1].data);
        }

        enum SearchState 
        {
            ContinueLastTime,
            Back,
            ForwToCheck
        }
        /// <summary>
        /// 找到 时间 dt 落在 [idx,idx+1] 之间的 idx;
        /// 返回 -1,证明dt 在列表在前面, 或列表数据量为=0,
        /// 当dt 大于 列表最后一个数, 返回最后一个数据的id
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list">列表</param>
        /// <param name="dt"></param>
        /// <param name="searchStartIdx">从列表的某个位置开始向前查找</param>
        /// <returns></returns>
        int searchIndex<T>(List<T> list, DateTime dt, int searchStartIdx ) where T: IDataTimeUnit
        {
            if (list.Count() == 0)
                return -1;

            int max_index = list.Count() - 1;

            if (dt >= list[max_index].dt)
                return max_index;

            if (dt < list[0].dt)
                return -1;


            int index = searchStartIdx;
            SearchState state = SearchState.ContinueLastTime;

            if ((index < 0) || (index >= max_index))//重新开始
            {
                index = max_index;
                state = SearchState.Back;
            }
            else if (state == SearchState.ContinueLastTime) 
            {
                if (list[index].dt <= dt)
                {
                    //可能找到了
                    //再向正方向看看
                    state = SearchState.ForwToCheck;
                }
                else
                {
                    state = SearchState.Back;
                }
            }

            if (state == SearchState.ForwToCheck)
            {
                while (true) 
                {
                    DateTime time = list[index].dt;
                    if (time > dt)
                    {
                        //就是之前那个
                        index--;
                        return index;
                    }
                    else
                    {
                        index++;
                    }
                    if (index > max_index)
                    {
                        //最后一个就是了
                        throw new Exception("之前没有判断出 时间点在列表后,异常!!");
                        //return max_index;
                    }
                }
            }
            else//SearchState.Back
            {
                while (true)
                {
                    DateTime time = list[index].dt;
                    if (time <= dt)
                    {
                        //就是它
                        return index;
                    }
                    index--;
                    if(index<0)
                    {
                        //不可能发生
                        throw new Exception("之前没有判断出 时间点在列表前,异常!!");
                    }
                }
            }
        }


        /// <summary>
        /// 获取时间对应的 位置点
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        int GetPos(DateTime dt)
        {
            //找到 时间落在 [idx,idx+1] 之间的
            int index = searchIndex(PosPool, dt, pos_start_idx);
            pos_start_idx = index;

            if (index < 0) 
                index = 0;

            return GetPos(dt, index);
        }

        /// <summary>
        /// 获取 高级版的 timegrid
        /// </summary>
        /// <param name="start_dt">开始时间</param>
        /// <param name="end_dt">结束时间</param>
        /// <returns></returns>

        public List<GridAdvUnit> GetTimeGridAdv(DateTime start_dt, DateTime end_dt)
        {
            List<GridAdvUnit> result = new List<GridAdvUnit>();

            for (int i = 0; i < ADPool.Count(); i++)
            {
                int idx = ADPool.Count() - 1 - i;
                if (ADPool[idx].dt < start_dt)
                {
                    break;
                }
                else if (ADPool[idx].dt <= end_dt)
                {
                    GridAdvUnit u = new GridAdvUnit();
                    u.dt = ADPool[idx].dt;
                    u.ad = ADPool[idx].data;

                    u.pos = GetPos(u.dt);
                    u.istatus = GetIStatus(u.dt);
                    result.Add(u);
                }
            }
            result.Reverse();
            return result;
        }

        enum GetGridAdvState 
        {
            FindEnd,
            FindMid,
            FindBegin,
            Finish
        }
        /// <summary>
        /// 从 end_dt 开始,向前查找, pos/posOfGrid 与 direction 相反方向变化, 直到 grid_start 为止
        /// </summary>
        /// <param name="direction"></param>
        /// <param name="grid_start"></param>
        /// <param name="grid_len"></param>
        /// <param name="end_dt"></param>
        /// <param name="posOfGrid"></param>
        /// <returns></returns>

        public List<GridAdvUnit> GetTimeGridAdv(DateTime end_dt, DIRECTION direction, int grid_start, int grid_len, int posOfGrid)
        {
            ResetSearch();
            List<GridAdvUnit> result = new List<GridAdvUnit>();
            int grid_mid = grid_start + grid_len / 2;
            int grid_begin = (direction == DIRECTION.FORWARD) ? grid_start : grid_start + grid_len - 1;
            GetGridAdvState state = GetGridAdvState.FindEnd;
            //肯定要经过grid_mid
            for (int i = 0; i < ADPool.Count(); i++)
            {
                int idx = ADPool.Count() - 1 - i;
                switch (state) 
                {
                    case GetGridAdvState.FindEnd:
                        if (ADPool[idx].dt <= end_dt) 
                        {
                            state = GetGridAdvState.FindMid;
                            GridAdvUnit u = new GridAdvUnit();
                            u.dt = ADPool[idx].dt;
                            u.ad = ADPool[idx].data;
                            u.pos = GetPos(u.dt);
                            u.istatus = GetIStatus(u.dt);
                            result.Add(u);
                        }
                        break;
                    case GetGridAdvState.FindMid:
                        {
                            GridAdvUnit u = new GridAdvUnit();
                            u.dt = ADPool[idx].dt;
                            u.ad = ADPool[idx].data;
                            u.pos = GetPos(u.dt);
                            u.istatus = GetIStatus(u.dt);
                            result.Add(u);

                            int grid = u.pos / posOfGrid;
                            if (direction == DIRECTION.FORWARD)
                            {
                                if (grid < grid_mid)
                                {
                                    //经过了一半数据,肯定没有错了
                                    state = GetGridAdvState.FindBegin;
                                }
                            }
                            else
                            {
                                if (grid > grid_mid)
                                {
                                    //经过了一半数据,肯定没有错了
                                    state = GetGridAdvState.FindBegin;
                                }
                            }
                        }
                        break;
                    case GetGridAdvState.FindBegin:
                        {
                            GridAdvUnit u = new GridAdvUnit();
                            u.dt = ADPool[idx].dt;
                            u.ad = ADPool[idx].data;
                            u.pos = GetPos(u.dt);
                            u.istatus = GetIStatus(u.dt);
                            result.Add(u);
                            int grid = u.pos / posOfGrid;

                            
                            if (direction == DIRECTION.FORWARD)
                            {
                                if (grid <= grid_begin)
                                {
                                    //找完了
                                    state = GetGridAdvState.Finish;
                                    goto _finish;
                                    
                                }
                            }
                            else
                            {
                                if (grid >= grid_begin)
                                {
                                    //找完了
                                    state = GetGridAdvState.Finish;
                                    goto _finish;
                                }
                            }

                        }
                        break;
                }
            }
        _finish:
            if (state != GetGridAdvState.Finish) 
            {
                logger.Error($"GetGridAdv({end_dt},{direction},start={grid_start},len={grid_len},posOfGrid={posOfGrid}) 不能在缓冲区找到完整的数据");
            }
            result.Reverse();
            return result;
        }
        void toGrid_step1(int[] grids_sum, int[] grids_cnt, int gridLen, int grid_idx, int ad) 
        {
            if ((grid_idx < 0) || (grid_idx >= gridLen))
            {
                return;
            }

            if (!Misc.MyBase.ISVALIDATA(ad))
                return;

            grids_cnt[grid_idx]++;
            grids_sum[grid_idx] += ad;
        }
        /// <summary>
        /// 把 TimeGridAdv 转为 Grid
        /// </summary>
        /// <param name="gridAdvUnits"></param>
        /// <param name="posOfGrid"></param>
        /// <param name="gridLen"></param>
        /// <returns></returns>
        public int[] ToGrid(IEnumerable<GridAdvUnit> gridAdvUnits, int posOfGrid, int gridLen) 
        {
            int[] grids_sum = new int[gridLen];
            int[] grids_cnt = new int[gridLen];

            int grid_idx_last = -1;
            //grid_idx 应该要连续变化,不是,那就插值
            foreach (var gridAdvUnit in gridAdvUnits)
            {
                int grid_idx = gridAdvUnit.pos / posOfGrid;
                if (grid_idx_last != -1 && (Math.Abs(grid_idx_last - grid_idx)>1))
                {
                    //步子太大,需要插值
                    if (grid_idx_last < grid_idx)
                    {
                        for (int i = grid_idx_last; i < grid_idx; i++) 
                        {
                            toGrid_step1(grids_sum, grids_cnt, gridLen, i, gridAdvUnit.ad);
                        }
                    }
                    else 
                    {
                        for (int i = grid_idx_last; i > grid_idx; i--)
                        {
                            toGrid_step1(grids_sum, grids_cnt, gridLen, i, gridAdvUnit.ad);
                        }
                    }
                }
                toGrid_step1(grids_sum, grids_cnt, gridLen, grid_idx, gridAdvUnit.ad);
                grid_idx_last = grid_idx;
            }
            
            for(int i=0;i< gridLen;i++)
            {
                if (grids_cnt[i] == 0)
                    grids_sum[i] = Misc.MyBase.NULL_VALUE;
                else
                    grids_sum[i] = (int)(grids_sum[i] / grids_cnt[i]);
            }
            return grids_sum;
        }


        /// <summary>
        /// 把 TimeGridAdv 转为 Grid,  adLag, 把AD值滞后 n * 1.28ms
        /// </summary>
        /// <param name="gridAdvUnits"></param>
        /// <param name="posOfGrid"></param>
        /// <param name="gridLen"></param>
        /// <param name="adLag"></param>
        /// <returns></returns>
        public int[] ToGrid(IEnumerable<GridAdvUnit> gridAdvUnits, int posOfGrid, int gridLen, int adLag)
        {
            int[] grids_sum = new int[gridLen];
            int[] grids_cnt = new int[gridLen];

            int grid_idx_last = -1;
            //grid_idx 应该要连续变化,不是,那就插值
            for (int j = 0; j < gridAdvUnits.Count(); j++)
            {
                var gridAdvUnit = gridAdvUnits.ElementAt(j);
                int j_lag = j - adLag;
                if (j_lag < 0)
                    j_lag = 0;
                else if (j_lag > gridAdvUnits.Count() - 1)
                    j_lag = gridAdvUnits.Count() - 1;

                var gridAdvUnit_lag = gridAdvUnits.ElementAt(j_lag);
                int ad = gridAdvUnit_lag.ad;

                int grid_idx = gridAdvUnit.pos / posOfGrid;
                if (grid_idx_last != -1 && (Math.Abs(grid_idx_last - grid_idx) > 1))
                {
                    //步子太大,需要插值
                    if (grid_idx_last < grid_idx)
                    {
                        for (int i = grid_idx_last; i < grid_idx; i++)
                        {
                            toGrid_step1(grids_sum, grids_cnt, gridLen, i, ad);
                        }
                    }
                    else
                    {
                        for (int i = grid_idx_last; i > grid_idx; i--)
                        {
                            toGrid_step1(grids_sum, grids_cnt, gridLen, i, ad);
                        }
                    }
                }
                toGrid_step1(grids_sum, grids_cnt, gridLen, grid_idx, ad);
                grid_idx_last = grid_idx;
            }

            for (int i = 0; i < gridLen; i++)
            {
                if (grids_cnt[i] == 0)
                    grids_sum[i] = Misc.MyBase.NULL_VALUE;
                else
                    grids_sum[i] = (int)(grids_sum[i] / grids_cnt[i]);
            }
            return grids_sum;
        }


        #region 子功能,grid 的 istatus 变化

        class GridIstatusPush
        {
            public int istatus_no;
            public event GridIStatusEventHander GridIStatusEvent;
            public void Notify(object sender, GridIStatusEventArgs e)
            {
                GridIStatusEvent?.Invoke(sender, e);
            }
            public bool IsNoEvent()
            {
                if (GridIStatusEvent == null)
                    return true;
                else
                    return false;
            }
        }
        List<GridIstatusPush> mGridIStatusEventList = new List<GridIstatusPush>();

        /// <summary>
        /// 添加事件
        /// </summary>
        /// <param name="istatus_no"></param>
        /// <param name="func"></param>
        public void GridIStatusEventAdd(int istatus_no, GridIStatusEventHander func)
        {
            var gs = from _g in mGridIStatusEventList
                     where _g.istatus_no == istatus_no
                     select _g;
            GridIstatusPush g;
            if (gs.Count() > 0)
            {
                g = gs.First();
                g.GridIStatusEvent += func;
            }
            else
            {
                g = new GridIstatusPush() { istatus_no = istatus_no };
                g.GridIStatusEvent += func;
                mGridIStatusEventList.Add(g);
            }
        }
        /// <summary>
        /// 删除事件
        /// </summary>
        /// <param name="istatus_no"></param>
        /// <param name="func"></param>
        public void GridIStatusEventDel(int istatus_no, GridIStatusEventHander func)
        {
            var gs = from _g in mGridIStatusEventList
                     where _g.istatus_no == istatus_no
                     select _g;
            GridIstatusPush g;
            if (gs.Count() > 0)
            {
                g = gs.First();
                g.GridIStatusEvent -= func;
                if (g.IsNoEvent())
                {
                    mGridIStatusEventList.Remove(g);
                }
            }
        }


        /// <summary>
        /// 触发GridIStatusEvent事件
        /// </summary>
        /// <param name="direction"></param>
        /// <param name="pos_start"></param>
        /// <param name="pos_len"></param>
        /// <param name="marker"></param>
        /// <param name="dt"></param>
        /// <param name="sender"></param>
        public void NotifyGridIStatusEvent(DIRECTION direction, int pos_start, int pos_len, int marker, DateTime dt, object sender)
        {
            if (mGridIStatusEventList.Count() <= 0)
                return;

            int start_idx;
            int end_idx;
            int start_pos;
            int end_pos;
            if (direction == DIRECTION.FORWARD)
            {
                start_pos = pos_start;
                end_pos = pos_start + pos_len - 1;
            }
            else
            {
                start_pos = pos_start + pos_len - 1;
                end_pos = pos_start;
            }



            bool ret = GetIdxFromPosPool(
                start_pos, dt, out start_idx, out end_idx);
            if (ret == false)//异常
                return;

            DateTime start_dt = PosPool[start_idx].dt;
            DateTime end_dt = dt;

            foreach (GridIstatusPush g in mGridIStatusEventList)
            {
                List<Range> data0;
                List<Range> data1;


                GetIStatusRange(
                    g.istatus_no, start_dt, end_dt,
                    direction, start_pos, end_pos,
                    out data0, out data1);
                g.Notify(sender, new GridIStatusEventArgs()
                {
                    direction = direction,
                    istatus_no = g.istatus_no,
                    marker = marker,
                    pos_start = pos_start,
                    pos_len = pos_len,
                    data_0 = data0,
                    data_1 = data1
                });
            }
        }


        void GetIStatusRange(
            int istatus_no,
            DateTime start_dt, DateTime end_dt,
            DIRECTION direction, int start_pos, int end_pos,
            out List<Range> data0, out List<Range> data1)
        {
            data0 = new List<Range>();
            data1 = new List<Range>();
            UInt16 istatus = GetIStatus(start_dt, out int istatus_idx);
            
            if (istatus_idx == -1)//异常,列表没有数据
            {
                //全部都是1
                if (direction == DIRECTION.FORWARD)
                    data1.Add(new Range() { Begin = start_pos, End = end_pos });
                else
                    data1.Add(new Range() { Begin = end_pos, End = start_pos });

                return;
            }
            bool istatus_no_b = Misc.MyBase.CHECKBIT(istatus, istatus_no );

            Range r = new Range();

            r.Begin = start_pos;

            for (int i = istatus_idx + 1; i < IStatusPool.Count(); i++)
            {
                istatus = IStatusPool[i].istatus;
                int pos = IStatusPool[i].pos;
                bool b = Misc.MyBase.CHECKBIT(istatus, istatus_no );
                if (IStatusPool[i].dt >= end_dt)
                {
                    //结束,这是最后!!!
                    break;
                }
                else
                {
                    if (b != istatus_no_b)
                    {
                        r.End = pos;
                        if (istatus_no_b)
                            data1.Add(r);
                        else
                            data0.Add(r);
                        istatus_no_b = b;
                        r = new Range();
                        r.Begin = pos;
                    }
                }
            }
            r.End = end_pos;
            if (istatus_no_b)
                data1.Add(r);
            else
                data0.Add(r);

            if (direction == DIRECTION.FORWARD)
            {
                for (int i = 0; i < data0.Count(); i++)
                {
                    data0[i].End -= 1;
                }
                for (int i = 0; i < data1.Count(); i++)
                {
                    data1[i].End -= 1;
                }
            }
            else
            {
                for (int i = 0; i < data0.Count(); i++)
                {

                    data0[i].End += 1;
                    int t = data0[i].End;
                    data0[i].End = data0[i].Begin;
                    data0[i].Begin = t;
                }
                data0.Reverse();


                for (int i = 0; i < data1.Count(); i++)
                {
                    data1[i].End += 1;
                    int t = data1[i].End;
                    data1[i].End = data1[i].Begin;
                    data1[i].Begin = t;
                }
                data1.Reverse();
            }
        }
        #endregion
    }
    interface IDataTimeUnit 
    {
        DateTime dt { get; set; }
    }
    struct DataTimeUnit: IDataTimeUnit
    {
        public int data;
        public DateTime dt { get; set; }
        public override string ToString()
        {
            return data.ToString() + " |" + dt.Ticks.ToString();
        }
    }
    struct DataTimeUnit2: IDataTimeUnit
    {
        public UInt16 istatus;
        public int pos;
        public DateTime dt { get; set; }
        public override string ToString()
        {
            return pos.ToString() + "(" + istatus.ToString("X2") + ") |" + dt.ToString();
        }
    }
}