using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Aitex.Core.RT.Log;
namespace Aitex.Core.Util
{
    /// 
    /// DeviceTimer类  
    /// 
    /// 设计目的:
    /// 1. 进行ms级别的定时;
    /// 2. 弥补使用Windows系统时间作为定时,如果系统时间被更改,定时器面临误判风险(Alpha机台已有多次发生类似事件);
    /// 
    /// 使用场合:
    /// 系统中凡是需要定时完成的事件,建议采用该定时器完成定时功能;
    /// 
    public class DeviceTimer
    {
        //引入高性能计数器API,通过对CPU计数完成计时
        [DllImport("Kernel32.dll")]
        private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
        //获取当前CPU的工作频率
        [DllImport("Kernel32.dll")]
        private static extern bool QueryPerformanceFrequency(out long lpFrequency);
        /// 
        /// 定时器内部状态定义
        /// 
        private enum DeviceTimerState
        {
            TM_ST_IDLE = 0,
            TM_ST_BUSY = 1,
            TM_ST_TIMEOUT = 2,
        }
        /// 
        /// 定时器内部状态
        /// 
        DeviceTimerState _state;
        /// 
        /// 定时器开始计时时刻的相对时间点
        /// 
        long _startTime;
        /// 
        /// 定时器超时时刻的相对时间点
        /// 
        long _timeOut;
        /// 
        /// CPU运行的时钟频率
        /// 
        double _freq;
        /// 
        /// 定时时间(单位:ms)
        /// 
        double _duration;
        /// 
        /// class constructure
        /// 
        public DeviceTimer()
        {
            long freq;
            if (QueryPerformanceFrequency(out freq) == false)
                throw new Exception("本计算机不支持高性能计数器");
            //得到每1ms的CPU计时TickCount数目
            _freq = (double)freq / 1000.0;
            SetState(DeviceTimerState.TM_ST_IDLE);
            QueryPerformanceCounter(out _startTime);
            _timeOut = _startTime;
            _duration = 0;
        }
        /// 
        /// 内部调用:设置定时器当前状态
        /// 
        /// 
        private void SetState(DeviceTimerState state)
        {
            _state = state;
        }
        /// 
        /// 内部调用:返回定时器当前状态
        /// 
        /// 
        private DeviceTimerState GetState()
        {
            return _state;
        }
        /// 
        /// 定时器开始计时到现在已流逝的时间(单位:毫秒)
        /// 
        /// 
        public double GetElapseTime()
        {
            long curCount;
            QueryPerformanceCounter(out curCount);
            return (double)(curCount - _startTime) / (double)_freq;
        }
        /// 
        /// 获取定时总时间
        /// 
        /// 
        public double GetTotalTime()
        {
            return _duration;
        }
        /// 
        /// 停止计时器计时
        /// 
        public void Stop()
        {
            SetState(DeviceTimerState.TM_ST_IDLE);
            QueryPerformanceCounter(out _startTime);
            _timeOut = _startTime;
            _duration = 0;
        }
        /// 
        /// 启动定时器
        /// 
        /// 定时时间(单位:毫秒)
        public void Start(double delay_ms)
        {
            QueryPerformanceCounter(out _startTime);
            _timeOut = Convert.ToInt64(_startTime + delay_ms * _freq);
            SetState(DeviceTimerState.TM_ST_BUSY);
            _duration = delay_ms;
        }
        /// 
        /// 重新开始定时器
        /// 开始的计时时间以上一次Start的时间为准
        /// 
        /// 定时时间(单位:毫秒)
        public void Restart(double delay_ms)
        {
            _timeOut = Convert.ToInt64(_startTime + delay_ms * _freq);
            SetState(DeviceTimerState.TM_ST_BUSY);
            _duration = delay_ms;
        }
        /// 
        /// 返回定时器是否超时
        /// 
        /// 
        public bool IsTimeout()
        {
            if (_state == DeviceTimerState.TM_ST_IDLE)
            {
                //System.Diagnostics.Debug.WriteLine("Warning: Misuage of the device timer. You must start it first before you can use it.");
                //System.Diagnostics.Debug.Assert(false, "Warning: Misuage of the device timer. You must start it first before you can use it.");
            }
            long curCount;
            QueryPerformanceCounter(out curCount);
            if (_state == DeviceTimerState.TM_ST_BUSY && (curCount >= _timeOut))
            {
                SetState(DeviceTimerState.TM_ST_TIMEOUT);
                return true;
            }
            else if (_state == DeviceTimerState.TM_ST_TIMEOUT)
            {
                return true;
            }
            return false;
        }
        /// 
        /// 定时器是否在工作中
        /// 
        /// 
        public bool IsIdle()
        {
            return (_state == DeviceTimerState.TM_ST_IDLE);
        }
    }
}