using System.Linq;
using Intrepid.Structures;

namespace Intrepid.Gameplay.Entities.Player.ActionBelt
{
    public class ActionStackBelt : StackBelt<ActionEnvelope>
    {
        public new bool Push(ActionEnvelope envelope)
        {
            var envelopesToRemove = Elements
                .Where(action => action.ActionIdentifier.Id.Equals(envelope.ActionIdentifier.Id))
                .ToList();

            foreach (var actionEnvelope in envelopesToRemove)
            {
                RemoveById(actionEnvelope.ActionIdentifier.Id);
            }
            return base.Push(envelope);
        }

        public bool RemoveById(string id, bool nextRight = true)
        {
            CurrentIndex = 0;
            Elements.RemoveAll(envelope => envelope.ActionIdentifier.Id == id);
            
            if (IsEmpty)
            {
                Focus = null;
                return false;
            }

            if (Focus.ActionIdentifier.Id != id) return false;
            if (nextRight)
            {
                NextRight();
            }
            else
            {
                NextLeft();
            }

            return true;
        }

        public bool RemoveByType(ActionCategory actionCategory, bool nextRight = true)
        {
            CurrentIndex = 0;
            Elements.RemoveAll(envelope => envelope.ActionCategory == actionCategory);
            
            if (IsEmpty)
            {
                Focus = null;
                return false;
            }

            if (Focus.ActionCategory != actionCategory) return false;
            if (nextRight)
            {
                NextRight();
            }
            else
            {
                NextLeft();
            }

            return true;
        }

        public bool RemoveByIdAndType(string id, ActionCategory actionCategory, bool nextRight = true)
        {
            CurrentIndex = 0;
            Elements.RemoveAll(envelope => envelope.ActionIdentifier.Id == id && envelope.ActionCategory == actionCategory);

            if (IsEmpty)
            {
                Focus = null;
                return false;
            }

            if (Focus.ActionIdentifier.Id != id || Focus.ActionCategory != actionCategory) return false;
            if (nextRight)
            {
                NextRight();
            }
            else
            {
                NextLeft();
            }
            
            return true;
        }
        
        public bool Contains(string id)
        {
            return Elements.Any(envelope => envelope.ActionIdentifier.Id == id);
        }
    }
}