using VOID.Generic.Dict;
using VOID.Generic.Objects.Item.Events;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Wearable;
using VOID.Generic.Objects.Wearable.Events;

namespace VOID.Generic.Objects.Unit.Actions
{
    public class UnEquipAction : AbstractAction
    {
        private readonly UnitObject _unit;
        private readonly WearableObject _item;

        public UnEquipAction(UnitObject unit, WearableObject item)
        {
            _unit = unit;
            _item = item;
        }

        public override bool IsInRange() => true;

        protected override void OnEndIt() {}

        protected override void OnCancelIt() {}
        
        public override void CanDoIt()
        {
            Check(
                state == ActionState.Ready,
                UnitActionErrorType.ActionStateIsNotReady);
            if (_unit.basicState.turnManager)
            {
                Check(
                    _unit.unitState.isSelfTurn,
                    UnitActionErrorType.UnitSelfTurnNotActive);
                Check(
                    _unit.unitData.currentResources.actionPoints >= 1,
                    UnitActionErrorType.UnitNotEnoughActionPoints);
            }
            Check(
                _unit.unitState.isControllable,
                UnitActionErrorType.UnitStateIsNotControllable);
            Check(
                _item.wearableState.wearerUnit == _unit,
                UnitActionErrorType.UnitDontWearThatItem);
        }

        protected override void OnDoIt()
        {
            if (_unit.basicState.turnManager)
                _unit.unitData.UseResource(UnitResourceType.ActionPoints, 1);
            
            var unEquipEvent = new UnEquipEvent
            {
                wearable = _item,
                unit = _unit
            };
            
            _item.wearableEvents.onUnEquippedBefore.Invoke(unEquipEvent);
            _unit.unitEvents.onUnEquipBefore.Invoke(unEquipEvent);

            Check(!unEquipEvent.prevented, UnitActionErrorType.UnEquipIsPrevented);
            
            BeforePerform();
            _unit.unitEquipment.UnEquip(_item);
            _unit.unitBackpack.Take(_item);
            _item.wearableEvents.onUnEquippedAfter.Invoke(unEquipEvent);
            _unit.unitEvents.onUnEquipAfter.Invoke(unEquipEvent);
            AfterPerform();
            EndIt();
        }
    }
}