using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using MECF.Framework.Simulator.Core.Driver;

namespace MECF.Framework.Simulator.Core.Aligners.HPA48
{
    public class HPA48Simulator : SerialPortDeviceSimulator
    {
        #region Variables

        private CancellationTokenSource _cancellationTokenSource;
        private readonly object _lock = new object();
        private bool _isBusy = false;

        #endregion

        #region Constructors

        public HPA48Simulator(string portName)
            : base(portName, -1, "", ' ')
        {

        }

        #endregion

        #region Properties

        public bool IsAlarm { get; set; }

        public bool IsVacuumOn { get; set; }

        public bool IsGenerateBALError { get; set; }

        #endregion

        #region Methods

        protected override void ProcessUnsplitMessage(string message)
        {
            if (message.StartsWith("ERS"))
                ERS(message);
            else if (message.StartsWith("BAL"))
                BAL(message);
            else if (message.StartsWith("HOM"))
                HOM(message);
            else if (message.StartsWith("CVN"))
                CVN(message);
            else if (message.StartsWith("CVF"))
                CVF(message);
            else if (message.StartsWith("CVD"))
                CVD(message);
            else if (message.StartsWith("MTM"))
                MTM(message);
            else if (message.StartsWith("DOC"))
                DOC(message);
            else if (message.StartsWith("STP"))
                STP(message);
            else if (message.StartsWith("PER"))
                PER(message);

        }

        protected override void ProcessWriteMessage(string msg)
        {
            var msgReformatted = $"{msg}\r\n";
            base.ProcessWriteMessage(msgReformatted);
        }

        private void SendResponse(string cmd, Action<string> handleCmd, Action customizeEcho = null)
        {
            lock (_lock)
            {
                if(_isBusy)
                    OnWriteMessage("BUSY");
                else
                {
                    if (_cancellationTokenSource == null)
                    {
                        _cancellationTokenSource = new CancellationTokenSource();
                        _isBusy = true;
                        Task.Run(() => { handleCmd?.Invoke(cmd); }, _cancellationTokenSource.Token).ContinueWith(t =>
                        {
                            lock (_lock)
                            {
                                _isBusy = false;

                                if(customizeEcho != null)
                                {
                                    try
                                    {
                                        customizeEcho?.Invoke();
                                    }
                                    catch (Exception ex)
                                    {
                                        Trace.WriteLine(ex.Message);
                                        Debugger.Break();
                                    }
                                }
                                else
                                    OnWriteMessage("END");
                                _cancellationTokenSource = null;
                            }
                        });
                    }
                }
            }
        }

        /// <summary>
        /// 开始寻边。
        /// </summary>
        /// <param name="cmd"></param>
        private void BAL(string cmd)
        {
           SendResponse(cmd, s =>
           {
               Thread.Sleep(3000);
           }, () =>
           {
               if(IsGenerateBALError)
                   OnWriteMessage("ERR 0411");
               else
                   OnWriteMessage("END");

           });
        }

        /// <summary>
        /// 回机械零点。
        /// </summary>
        /// <param name="cmd"></param>
        private void HOM(string cmd)
        {
            SendResponse(cmd, s =>
            {
                Thread.Sleep(3000);
            });
        }

        /// <summary>
        /// 读取真空值
        /// </summary>
        /// <param name="cmd"></param>
        private void CVD(string cmd)
        {
            SendResponse(cmd, s =>
            {
                Thread.Sleep(500);
                OnWriteMessage("-65");
            });
        }

        /// <summary>
        /// 打开真空。
        /// </summary>
        /// <param name="cmd"></param>
        private void CVN(string cmd)
        {
            SendResponse(cmd, s =>
            {
                Thread.Sleep(500);
                IsVacuumOn = true;
            });
        }

        /// <summary>
        /// 关闭真空。
        /// </summary>
        /// <param name="cmd"></param>
        private void CVF(string cmd)
        {
            SendResponse(cmd, s =>
            {
                Thread.Sleep(500);
                IsVacuumOn = false;
            });
        }

        /// <summary>
        /// 清除所有报警。
        /// </summary>
        /// <param name="cmd"></param>
        private void ERS(string cmd)
        {
            SendResponse(cmd, s =>
            {
                Thread.Sleep(100);
                IsAlarm = false;
            });
        }

        /// <summary>
        /// 读取上一次报警
        /// </summary>
        /// <param name="cmd"></param>
        private void PER(string cmd)
        {
            SendResponse(cmd, s =>
            {
                Thread.Sleep(500);
                OnWriteMessage("ERR 444");
            });
        }

        /// <summary>
        /// 移动至测量中心点。
        /// </summary>
        /// <param name="cmd"></param>
        private void MTM(string cmd)
        {
            SendResponse(cmd, s =>
            {
                Thread.Sleep(1000);
            });
        }

        /// <summary>
        ///检测是否有Wafer。
        /// </summary>
        /// <param name="cmd"></param>
        private void DOC(string cmd)
        {
            SendResponse(cmd, s =>
            {
                Thread.Sleep(1000);
                OnWriteMessage("1");
            });
        }

        /// <summary>
        /// 停止运动。
        /// </summary>
        /// <param name="cmd"></param>
        private void STP(string cmd)
        {
            _cancellationTokenSource?.Cancel();
        }

        #endregion
    }
}
