using System;
using VOID.Generic.Objects.Unit.Actions;
using VOID.Generic.Objects.Usable;
using VOID.Generic.Player.Input;
using VOID.Generic.Player.Util;
using VOID.UserInterface.Game;

namespace VOID.Generic.Player.CursorOperation
{
    public class OnUsableCursorOperation : AbstractCursorOperation
    {
        public override Type ForType() => typeof(UsableObject);

        public override bool Check(SelectUtilResult select)
        {
            return select.selectObject is UsableObject;
        }

        public override void DoDefault(SelectUtilResult select, bool isAlternate)
        {
            if (isAlternate) return;
            
            var usable = (UsableObject)select.selectObject;
            var activeUnit = PlayerController.current.activeUnit;
            var carrier = usable.itemState.carriedBy;
            var attackAbility = activeUnit.unitAbilityBook.attackAbility;

            activeUnit.OrderStop();
            if (activeUnit.unitData.canAttack && PlayerInputManager.current.isForceAttack)
            {
                // Player forced attack action
                activeUnit.Order(new MoveAction(activeUnit, select.position, attackAbility.range));
                activeUnit.Order(new AbilityAction(activeUnit, attackAbility, select.position));
            }
            else if (activeUnit.unitData.canTake && usable.itemData.canBePicked && usable.itemData.canBeMoved && (carrier == null || carrier.basicState.isDead))
            {
                // Default operation is TAKE (+ move closer if needed)
                activeUnit.Order(new MoveAction(activeUnit, usable.transform.position, activeUnit.unitData.takeRange));
                activeUnit.Order(new TakeAction(activeUnit, usable));
            }
            else if(activeUnit.unitData.canUse)
            {
                // If can't be taken then... USE (+ move closer if needed)
                activeUnit.Order(new MoveAction(activeUnit, usable.transform.position, activeUnit.unitData.useRange));
                activeUnit.Order(new UseAction(activeUnit, usable));
            }
        }

        public override void DoContext(SelectUtilResult select)
        {
            var usable = (UsableObject)select.selectObject;
            var activeUnit = PlayerController.current.activeUnit;
            var attackAbility = activeUnit.unitAbilityBook.attackAbility;
            var carrier = usable.itemState.carriedBy;

            ContextMenuUI.current.Prepare();
            
            ContextMenuUI.current.AddBeforeClick(() => activeUnit.OrderStop());
            if (activeUnit.unitData.canUse)
            {
                ContextMenuUI.current.AddOption("Use", () =>
                {
                    activeUnit.Order(new MoveAction(activeUnit, usable.transform.position, activeUnit.unitData.takeRange));
                    activeUnit.Order(new UseAction(activeUnit, usable));
                });
            }
            if (!select.onUI)
            {
                if (activeUnit.unitData.canMove)
                {
                    ContextMenuUI.current.AddOption("Move", () =>
                    {
                        activeUnit.Order(new MoveAction(activeUnit, usable.transform.position));
                    });
                }
                if (activeUnit.unitData.canAttack)
                {
                    ContextMenuUI.current.AddOption("Attack", () =>
                    {
                        activeUnit.Order(new MoveAction(activeUnit, select.position, attackAbility.range));
                        activeUnit.Order(new AbilityAction(activeUnit, attackAbility, select.position));
                    });
                }
            }

            if (activeUnit.unitData.canTake && usable.itemData.canBePicked && usable.itemData.canBeMoved && (carrier == null || carrier.basicState.isDead))
            {
                ContextMenuUI.current.AddOption("Take", () =>
                {
                    activeUnit.Order(new MoveAction(activeUnit, usable.transform.position, activeUnit.unitData.takeRange));
                    activeUnit.Order(new TakeAction(activeUnit, usable));
                });
            }

            if (carrier == activeUnit)
            {
                ContextMenuUI.current.AddOption("Drop", () =>
                {
                    activeUnit.Order(new DropAction(activeUnit, usable));
                });
            }
            if (activeUnit.unitData.canInspect && usable.basicData.canBeInspected)
            {
                ContextMenuUI.current.AddOption("Inspect", () =>
                {
                    MoveAction moveAction = new MoveAction(activeUnit, usable.transform.position, activeUnit.unitData.inspectRange);
                    moveAction.OnEnd += () => activeUnit.OrderInstantly(new InspectAction(activeUnit, usable));
                    activeUnit.Order(moveAction);
                });
            }
            ContextMenuUI.current.Open();
        }
    }
}