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

namespace VIZ.Framework.Core
{
    /// <summary>
    /// 循环管理器
    /// </summary>
    public class LoopManager : ILoopManager
    {
        /// <summary>
        /// 日志
        /// </summary>
        private static ILog log = LogManager.GetLogger(typeof(LoopManager));

        /// <summary>
        /// 循环信息池
        /// </summary>
        private Dictionary<string, LoopInfo> pool = new Dictionary<string, LoopInfo>();

        /// <summary>
        /// 循环线程
        /// </summary>
        private System.Threading.Thread thread;

        /// <summary>
        /// 线程信息
        /// </summary>
        private LoopThreadInfo threadInfo;

        /// <summary>
        /// 注册
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="intervalSec">间隔（单位：秒）</param>
        /// <param name="action">行为</param>
        public void Register(string key, double intervalSec, Action action)
        {
            lock (this.pool)
            {
                LoopInfo info = new LoopInfo();
                info.Key = key;
                info.WaitTime = TimeSpan.FromSeconds(intervalSec);
                info.BeginTime = DateTime.Now;
                info.Action = action;
                info.LastTriggerTime = DateTime.Now;

                this.pool[key] = info;
            }
        }

        /// <summary>
        /// 注销
        /// </summary>
        /// <param name="key">键</param>
        public void UnRegister(string key)
        {
            lock (this.pool)
            {
                if (this.pool.ContainsKey(key))
                {
                    this.pool.Remove(key);
                }
            }
        }

        /// <summary>
        /// 开始
        /// </summary>
        public void Start()
        {
            this.Stop();

            this.threadInfo = new LoopThreadInfo();
            this.thread = new System.Threading.Thread(this.Execute);
            this.thread.IsBackground = true;
            this.thread.Start();
        }

        /// <summary>
        /// 停止
        /// </summary>
        public void Stop()
        {
            if (this.threadInfo != null)
            {
                this.threadInfo.IsCancel = true;
            }

            this.threadInfo = null;
            this.thread = null;
        }

        /// <summary>
        /// 销毁
        /// </summary>
        public void Dispose()
        {
            this.Stop();
        }

        /// <summary>
        /// 执行
        /// </summary>
        private void Execute()
        {
            LoopThreadInfo info = this.threadInfo;
            if (info == null)
                return;

            while (!info.IsCancel)
            {
                lock (this.pool)
                {
                    DateTime now = DateTime.Now;

                    foreach (LoopInfo item in this.pool.Values)
                    {
                        if (item == null)
                            continue;

                        if (now >= item.LastTriggerTime + item.WaitTime)
                        {
                            try
                            {
                                item.Action();
                                item.LastTriggerTime = now;
                            }
                            catch (Exception ex)
                            {
                                log.Error(ex);
                                item.LastTriggerTime = now;
                            }
                        }
                    }
                }

                System.Threading.Thread.Sleep(500);
            }
        }
    }
}
