using System.Collections.Generic;
using Intrepid.Localization;
using Intrepid.Utilities;
using Sirenix.OdinInspector;
using UnityEngine;

namespace Intrepid.Gameplay.Entities.Player.ActionBelt
{
    public abstract class ActionCallable : Identification
    {
        [GroupConfigurations, SerializeField, EnumPaging] private ActionCategory actionCategory = ActionCategory.General;
        [GroupConfigurations, SerializeField, EnumPaging] private ActionActivationMode activationMode = ActionActivationMode.Instant;
        [ShowIf(nameof(IsHoldActivation))]
        [GroupConfigurations, SerializeField, Range(0, 5)] private float holdDuration = 1.5f;
        [GroupConfigurations, SerializeField, ToggleLeft, PropertySpace] private bool canBeDropped;
        [ShowIf(nameof(IsNotTerminal))]
        [GroupConfigurations, SerializeField, ToggleLeft, PropertySpace] private bool shouldDropFromBeltWhenActivated;

        private bool IsNotTerminal => actionCategory != ActionCategory.Terminal;
        private bool IsHoldActivation => activationMode == ActionActivationMode.Hold;
        
        protected ActionCategory ActionCategory => actionCategory;
        protected ActionActivationMode ActivationMode => activationMode;
        protected float HoldDuration => IsHoldActivation ? holdDuration : 0f;

        protected bool CanBeDropped => canBeDropped;
        protected bool ShouldDropFromBeltWhenActivated => shouldDropFromBeltWhenActivated;
        protected virtual LocalizationTag ActionLocalization { get; }
        protected virtual LocalizationTag DescriptionLocalization { get; }
        protected virtual List<string> Parameters { get; } = new();

        public bool IsEnabled { get; protected set; } = true;
        public bool IsNotEnabled => !IsEnabled;
        
        protected abstract void Execute(ActionIdentifier identifier);

        public virtual ActionEnvelope BuildEnvelope()
        {
            return new ActionEnvelope
            {
                ActionIdentifier = new ActionIdentifier
                {
                    Id = Id,
                },
                CanBeDropped = CanBeDropped,
                ActionCategory = ActionCategory,
                ActivationMode = ActivationMode,
                HoldDuration = HoldDuration,
                ActionLocalization = ActionLocalization,
                DescriptionLocalization = DescriptionLocalization,
                DescriptionParams = Functions.GetParams(Parameters),
                Callback = ai =>
                {
                    Execute(ai);
                    return ActionCategory.Terminal.Equals(ActionCategory) || ShouldDropFromBeltWhenActivated;
                }
            };
        }
    }
}