using System.Linq;
using Machinations.FromFlash.graph;

namespace Machinations.FromFlash.machinations.model
{
    /// <summary>
    /// a node of machinations framework, able to consume resoures on one side, and while sitisfied, generating new resources
    /// </summary>
    public class Converter : Source
    {
        public Converter()
        {
            m_activationMode = ActivationMode.Passive;
        }

        public override NodeClass NodeClass => NodeClass.Converter;

        public override void Fire()
		{
            m_inputs.ForEach(input =>
            {
                if (input is StateConnection && ((StateConnection) input).Inhibited) return;
            });
            SetFiring();
            Pull();
            LogSelf();
        }

        public override void Satisfy()
		{
			if (!m_inhibited) 
            {
                m_outputs.ForEach(output =>
                {
                    if (output is StateConnection)
                    {
                        ((StateConnection) output).Fire();
                    }
                });
			}
            base.Satisfy();
		}
		
		public override void CheckInhibition() 
		{
			bool inhibited = m_inhibited;
			m_inhibited = false;
            m_inputs.ForEach(input =>
            {
                var connection = input as ResourceConnection;
                connection?.CheckInhibition(false);
            });
            m_inhibited = inhibited;
			base.CheckInhibition();
		}	
		
		public bool CanDrain()
        {
            return !m_inputs.Any(input =>
            {
                StateConnection connection = input as StateConnection;
                if (connection != null && !(connection.Start is Delay) && !(connection.Start is Gate) &&
                    connection.Label.Type !=  LabelType.Trigger && connection.Label.Type !=  LabelType.ReverseTrigger &&
                    !connection.Label.CheckCondition(connection.State))
                    {
                        return true;
                    }
                return false;
            });
		}
		
		
		public override string ToMMString()
        {
			return GetMMWhen() + " " + GetMMAct() + " " + GetMMHow() + " converter " + GetMMName();
        }

        protected override void InhibitedChangeForReal()
        {
            base.InhibitedChangeForReal();
            m_inputs.ForEach(input =>
            {
                var connection = input as ResourceConnection;
                connection?.CheckInhibition(false);
            });
        }
    }
}
