using System;
using System.Collections.Generic;
using System.ComponentModel.Design.Serialization;
using System.Globalization;
using System.Linq;
using System.Text;
namespace Aitex.Core.RT.IOCore
{
    /*
     * 
  
    
  
     * 
     */
    class InterlockAction
    {
        private List _limits = new List();
        private DOAccessor _do;
        private bool _actionValue;
        private string _actionstringValue;
        private string _tip;
        private Dictionary _cultureTip = new Dictionary();
        private string _actionName;
        public string ActionName => _do != null ? _do.Name : _actionName;
        public string Condition { get; set; }//KEEP,DELAY
        public float ConditionTime { get; set; }//和Condition配合使用
        public DOAccessor ActionDo => _do;
        public bool IsReverse => _isReverse;
        private bool _isReverse;
        public bool IsAuto => _isAuto;
        private bool _isAuto;
        public bool ActionValue => _actionValue;
        public List Limits => _limits;
        public string Tip => _tip;
        public InterlockAction(DOAccessor doItem, bool value, string tip, Dictionary cultureTip, List limits, bool isReverse)
        {
            _do = doItem;
            _actionValue = value;
            _tip = tip;
            _cultureTip = cultureTip;
            _limits = limits;
            _isReverse = isReverse;
        }
        public InterlockAction(DOAccessor doItem, string value, string tip, Dictionary cultureTip, List limits)
        {
            _do = doItem;
            _actionstringValue = value;
            _tip = tip;
            _cultureTip = cultureTip;
            _limits = limits;
        }
        public InterlockAction(DOAccessor doItem, bool value, string tip, string condition, float conditionTime, List limits, bool auto = true)
        {
            _do = doItem;
            _actionValue = value;
            _tip = tip;
            _limits = limits;
            _isAuto = auto;
            Condition = condition;
            ConditionTime = conditionTime;
        }
        public InterlockAction(string actionName, bool value, string tip, string condition, float conditionTime, List limits, bool auto)
        {
            _actionName = actionName;
            _actionValue = value;
            _tip = tip;
            _limits = limits;
            _isAuto = auto;
            Condition = condition;
            ConditionTime = conditionTime;
        }
        public bool IsSame(string doName, string value)
        {
            return (doName == ActionName) && (_actionstringValue == value);
        }
        public bool IsSame(string doName, bool value)
        {
            return (doName == ActionName) && (_actionValue == value);
        }
        public bool Reverse(out string reason)
        {
            reason = string.Empty;
            if (_do.Value != _actionValue)
                return false;
            if (_do.SetValue(!_actionValue, out reason))
            {
                reason = string.Format("Force setting DO-{0}({1}) = [{2}]", _do.IoTableIndex, _do.Name, (!_actionValue) ? "ON" : "OFF");
            }
            return true;
        }
        public bool CanDo(out string reason)
        {
            reason = string.Empty;
            bool result = true;
            bool cando;
            foreach (var interlockLimit in _limits)
            {
                string info;
                cando = interlockLimit.CanDo(out info);
                if (!cando)
                {
                    if (reason.Length > 0)
                        reason += "\n";
                    else
                    {
                        reason = string.Format("Interlock triggered, DO-{0}({1}) can not be [{2}], {3} \n", _do.IoTableIndex, _do.Name, _actionValue ? "ON" : "OFF",
                            _tip);
                    }
                    reason += info;
                }
                switch (interlockLimit.Condition.ToUpper())
                {
                    case "AND":
                        result = result && cando;
                        break;
                    case "OR":
                        result = result || cando;
                        break;
                }
            }
            return result;
        }
    }
}