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

namespace Aitex.Core.RT.IOCore.Interlock.Actions
{
	public abstract class InterlockActionBase : IInterlockAction
	{
		#region Variables

		private readonly List<List<IInterlockLimit>> _logicOrGroups;
		private readonly List<IInterlockLimit> _limits;
		private readonly string _tip;
		private Dictionary<string, string> _cultureTip;

		protected readonly string _module;
        protected readonly DOAccessor _do;
        protected readonly bool _actionValue;

		#endregion

		#region Constructors

		protected InterlockActionBase(string module, DOAccessor doItem, bool value, string tip, Dictionary<string, string> cultureTip)
		{
			_module = module;
			_logicOrGroups = new();
			_limits = new();
			_do = doItem;
			_actionValue = value;
			_tip = tip;
			_cultureTip = cultureTip;

		}

        #endregion

        #region Properties

        /// <summary>
        /// <inheritdoc cref="IInterlockAction.ActionName"/>
        /// </summary>
        public string ActionName => (_do != null) ? _do.Name : "";


        /// <summary>
        /// <inheritdoc cref="IInterlockAction.Limits"/>
        /// </summary>
        public IEnumerable<IInterlockLimit> Limits => _limits.AsReadOnly();


        /// <summary>
        /// <inheritdoc cref="IInterlockAction.LogicOrGroups"/>
        /// </summary>
        public IEnumerable<IEnumerable<IInterlockLimit>> LogicOrGroups => _logicOrGroups.AsReadOnly();

        #endregion

        #region Methods


        /// <summary>
        /// <inheritdoc cref="IInterlockAction.AddLimit"/>
        /// </summary>
        public void AddLimit(IInterlockLimit limit)
		{
			_limits.Add(limit);
		}

        /// <summary>
        /// <inheritdoc cref="IInterlockAction.AddLogicOrGroup"/>
        /// </summary>
        public void AddLogicOrGroup(List<IInterlockLimit> orGroup)
		{
			_logicOrGroups.Add(orGroup);
		}

        /// <summary>
        /// <inheritdoc cref="IInterlockAction.IsSame"/>
        /// </summary>
        public bool IsSame(string doName, bool value)
        {
            return string.Equals(doName, _do.Name, StringComparison.CurrentCultureIgnoreCase)
                   && _actionValue == value;
        }

        /// <summary>
        /// <inheritdoc cref="IInterlockAction.CanDo"/>
        /// </summary>
        public bool CanDo(out string reason)
		{
			reason = string.Empty;
			var sbReason = new StringBuilder();
			var result = true;
			foreach (var limit in _limits)
			{
				if (!limit.CanDo(out var limitReason))
				{
					sbReason.AppendLine(limitReason);
					result = false;
				}
			}

			// 如果有互锁被触发，则打印互锁信息
			if (!result)
			{
				sbReason.Insert(0,
					$"Interlock triggered, DO-{_do.IoTableIndex}({_do.Name}) can not be [{(_actionValue ? "ON" : "OFF")}]{(string.IsNullOrEmpty(_tip) ? "" : $",{_tip}")} \r\n");
				reason = sbReason.ToString().TrimEnd('\r', '\n');
			}

			return result;
		}

        /// <summary>
        /// <inheritdoc cref="IInterlockAction.Monitor"/>
        /// </summary>
        public abstract void Monitor();
        
		/// <inheritdoc cref="object.ToString()"/>
		public override string ToString()
		{
			return $"{ActionName}, Action={_actionValue}, Limit Count={Limits.Count()}, OR Group Count={LogicOrGroups.Count()}";
		}

		#endregion
	}
}
