using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Threading;

namespace FObjBase
{
    /// <summary>
    /// 循环执行模块,可以认为就是定时器系统
    /// </summary>
    public class PollModule
    {
        /// <summary>
        /// Poll_Config 的动作,添加,删除
        /// </summary>
        public enum POLL_CONFIG
        {
            /// <summary>
            /// 添加
            /// </summary>
            ADD, 
            /// <summary>
            /// 删除
            /// </summary>
            REMOVE
        }
        /// <summary>
        /// 循环执行的事件
        /// </summary>
        public delegate void PollHandler();
        /// <summary>
        /// 静态的实例,平常就是只用它
        /// </summary>
        public static PollModule Current = new PollModule();
        /// <summary>
        /// 精确执行,也就是一次OnPoll 一直While ,直到时间结束
        /// </summary>
        public bool IsAccurate = false;
        
        class PollStruct 
        {
            public PollHandler pollfunc;
            public TimeSpan ts;
            public DateTime dt = DateTime.MinValue;
            public bool bJustOnce;
            public object owner;
            public int markno;
        }
        List<PollStruct> pollmember = new List<PollStruct>();

        /// <summary>
        /// 以100ms 为周期, 多次执行
        /// </summary>
        /// <param name="pollfunc"></param>
        public void Poll_Config(PollHandler pollfunc)
        {
            Poll_Config(POLL_CONFIG.ADD, pollfunc);
        }

        /// <summary>
        /// 以100ms 为周期, 多次执行
        /// </summary>
        /// <param name="action"></param>
        /// <param name="pollfunc"></param>
        public void Poll_Config(POLL_CONFIG action, PollHandler pollfunc) 
        {
            Poll_Config(action, pollfunc, new TimeSpan(TimeSpan.TicksPerMillisecond * 100));
        }
        
        /// <summary>
        /// 多次周期执行
        /// </summary>
        /// <param name="action"></param>
        /// <param name="pollfunc"></param>
        /// <param name="ts"></param>
        public void Poll_Config(POLL_CONFIG action, PollHandler pollfunc, TimeSpan ts)
        {
            Poll_Config(action, pollfunc, ts, true, false, null, 0, false);
        }
        
        /// <summary>
        /// 添加或删除 poll func, 当pollfunc 本来已经存在,再次添加,只会使计时重新,或不管!!
        /// </summary>
        /// <param name="action">动作,添加?删除?</param>
        /// <param name="pollfunc">周期执行函数</param>
        /// <param name="ts">时间间隔</param>
        /// <param name="bRestart">重新计算数据</param>
        /// <param name="bActByNow">立刻执行?</param>
        /// <param name="owner">该函数的拥有者</param>
        /// <param name="markno">对func的标识码</param>
        /// <param name="bJustOnce">只执行一次</param>
        public void Poll_Config(POLL_CONFIG action, PollHandler pollfunc, TimeSpan ts, bool bRestart,  bool bActByNow, object owner, int markno, bool bJustOnce) 
        {
            if (action == POLL_CONFIG.ADD)
            {
                //周期执行的,执行周期最小为1ms
                if ((ts.TotalMilliseconds) < 1 && (bJustOnce == false))
                    ts = new TimeSpan(TimeSpan.TicksPerMillisecond);

                PollStruct ps;
                if (owner == null)
                {
                    ps = pollmember.Find(p => p.pollfunc == pollfunc);
                }
                else 
                {
                    ps = pollmember.Find(p => p.owner == owner && p.markno == markno);
                }

                if (ps == null)//新的!!!!
                {
                    ps = new PollStruct() { pollfunc = pollfunc, ts = ts, owner = owner, markno = markno };
                    pollmember.Add(ps);
                }
                else
                {
                    if (ps.ts != ts) 
                    {
                        ps.ts = ts;
                    }
                    if (bRestart)
                    {
                        ps.dt = DateTime.MinValue;
                    }
                }
                
                ps.bJustOnce = bJustOnce;

                if (bActByNow) //立刻执行
                {
                    ps.dt = DateTime.MaxValue;
                }
            }
            else
            {
                if (owner == null)
                {
                    Poll_Remove(pollfunc);
                }
                else
                {
                    Poll_Remove(owner,markno);
                }
            }
        }
        public void Poll_Remove(PollHandler pollfunc) 
        {
            pollmember.RemoveAll(p => p.pollfunc == pollfunc);
        }
        public void Poll_Remove(object owner, int markno)
        {
            pollmember.RemoveAll(p => p.owner == owner && p.markno == markno);
        }

        /// <summary>
        /// 多次周期执行
        /// </summary>
        /// <param name="pollfunc"></param>
        /// <param name="ts"></param>
        public void Poll_Config(PollHandler pollfunc, TimeSpan ts)
        {
            Poll_Config(pollfunc, ts, true, false, null, 0, false);
        }

        /// <summary>
        /// 添加或删除 poll func, 当pollfunc 本来已经存在,再次添加,只会使计时重新,或不管!!
        /// </summary>
        /// <param name="pollfunc">周期执行函数</param>
        /// <param name="ts">时间间隔</param>
        /// <param name="bRestart">重新计算数据</param>
        /// <param name="bActByNow">立刻执行?</param>
        /// <param name="owner">该函数的拥有者</param>
        /// <param name="markno">对func的标识码</param>
        /// <param name="bJustOnce">只执行一次</param>
        public void Poll_Config(PollHandler pollfunc, TimeSpan ts, bool bRestart, bool bActByNow, object owner, int markno, bool bJustOnce)
        {
            Poll_Config(POLL_CONFIG.ADD, pollfunc, ts, bRestart, bActByNow, owner, markno, bJustOnce);
        }
        public void OnPoll()
        {
            DateTime dt = DateTime.Now;
            PollStruct ps;
            for (int i = 0; i < pollmember.Count(); i++) 
            {
                ps = pollmember[i];
                while (true)
                {
                    bool toact = false;
                    if (ps.dt == DateTime.MaxValue)//立刻执行
                    {
                        ps.dt = dt;
                        toact = true;
                    }
                    else if (ps.dt == DateTime.MinValue) //刚加入
                    {
                        ps.dt = dt;
                    }
                    else 
                    {
                        TimeSpan ts = dt - ps.dt;
                        if (ts<TimeSpan.Zero)//异常,有人改了系统时间,时间回到从前了
                        {
                            ps.dt = dt;
                        }
                        else if (ts >= ps.ts)//够钟了!!
                        {

                            if (IsAccurate)//精密!!!!
                            {
                                ps.dt = ps.dt + ps.ts;
                                //当超过得太多,没法精确了,超过了10次
                                //if (ps.ts.TotalMilliseconds * 20 < ts.TotalMilliseconds)
                                //{
                                //    ps.dt = dt;
                                //}
                            }
                            else
                            {
                                ps.dt = dt;
                            }
                            toact = true;
                        }
                    }

                    if (toact)
                    {
                        ps.pollfunc();
                        if (ps.bJustOnce)
                        {
                            //从列表中删除
                            pollmember.Remove(ps);
                            i--;
                        }
                        else if (IsAccurate) 
                        {
                            continue;
                        }
                    }
                    break;
                }
            }
        }
        /// <summary>
        /// 只为了延时操作,同一周期多次添加同一func,只会调到一次!!!
        /// </summary>
        /// <param name="pollfunc"></param>
        /// <param name="owner"></param>
        /// <param name="markno"></param>
        public void Poll_JustOnce(PollHandler pollfunc, object owner, int markno) 
        {
            Poll_Config(POLL_CONFIG.ADD, pollfunc, new TimeSpan(), false, true, owner, markno, true);
        }
        static DateTime dt_last = DateTime.Now;
        System.Windows.Threading.DispatcherTimer timer;
        public Dispatcher Dispatcher;
        /// <summary>
        /// 不需要自己创建实例,因为已经创建了静态的对象
        /// </summary>
        public PollModule() 
        {
            timer = new System.Windows.Threading.DispatcherTimer();
            timer.Interval = TimeSpan.FromMilliseconds(1);
            timer.Tick += (s, e) =>
            {
                if (mylock != true)//不能让它能重入
                {
                    mylock = true;
                    OnPoll();
                    mylock = false;
                }  
            };
            Dispatcher = timer.Dispatcher;
        }
        bool mylock=false;
        /// <summary>
        /// 启动OnPoll
        /// </summary>
        public void Start() 
        {
            timer.Start();
        }
        /// <summary>
        /// 停止OnPoll
        /// </summary>
        public void Stop() 
        {
            timer.Stop();
        }
    }
    
}