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 abstract class MonitorTaskBase
    {
        /// <summary>
        /// 日志
        /// </summary>
        private static ILog log = LogManager.GetLogger(typeof(MonitorTaskBase));

        /// <summary>
        /// 名称
        /// </summary>
        public abstract string Name { get; }

        /// <summary>
        /// 监视间隔（单位：毫秒）
        /// </summary>
        public abstract int Interval { get; }

        /// <summary>
        /// 监控信息
        /// </summary>
        public abstract MonitorInfolBase Info { get; }

        /// <summary>
        /// 触发器集合
        /// </summary>
        public List<IMonitorTrigger> Triggers { get; private set; } = new List<IMonitorTrigger>();

        /// <summary>
        /// 任务信息
        /// </summary>
        private MonitorTaskInfo TaskInfo;

        /// <summary>
        /// 执行任务
        /// </summary>
        private Task ExecuteTask;

        /// <summary>
        /// 开始
        /// </summary>
        public void Start()
        {
            MonitorTaskInfo info = new MonitorTaskInfo();
            this.TaskInfo = info;

            this.ExecuteTask = Task.Run(() =>
            {
                while (!info.IsCancel)
                {
                    this.Execute();
                    this.ExecuteTrigger();

                    System.Threading.Thread.Sleep(this.Interval);
                }
            });
        }

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

        /// <summary>
        /// 执行触发器
        /// </summary>
        protected void ExecuteTrigger()
        {
            foreach (IMonitorTrigger trigger in this.Triggers)
            {
                try
                {
                    if (!trigger.CanExecute(this.Info))
                        continue;

                    trigger.Execute(this.Info);
                }
                catch (Exception ex)
                {
                    log.Error(ex);
                }
            }
        }

        /// <summary>
        /// 执行
        /// </summary>
        protected abstract void Execute();
    }
}
