using Sirenix.OdinInspector.Editor.Validation;
using Sirenix.Utilities;
using VOID.Editor.AttributeValidator;
using VOID.Generic.DropTable;
using VOID.Generic.Objects.Abstract;
using VOID.Generic.Objects.Container;
using VOID.Generic.Objects.Unit;

[assembly: RegisterValidator(typeof(DropTableComponentValidator))]

namespace VOID.Editor.AttributeValidator
{
    public class DropTableComponentValidator : ValueValidator<DropTableComponent>
    {
        protected override void Validate(ValidationResult result)
        {
            if (Value == null) return;

            var attachedTo = Value.GetComponent<AbstractObject>();
            
            IsPlacedWithAbstractObject(result, attachedTo);

            if (attachedTo == null) return;
            
            CanUseTriggerOnSpawn(result, attachedTo);
            IsDropTableDefined(result);
        }

        private void IsPlacedWithAbstractObject(ValidationResult result, AbstractObject attachedTo)
        {
            // DropTable's GameObject also needs to have AbstractObject (or its children)
            if (attachedTo != null) return;
            
            result.AddError($"{nameof(DropTableComponent)} needs to be placed together with any <u><b>{nameof(AbstractObject)}</b></u>");
        }

        private void CanUseTriggerOnSpawn(ValidationResult result, AbstractObject attachedTo)
        {
            // OnSpawn can be used only with Unit or Container
            if (Value.trigger is not DropTableTrigger.OnSpawn || attachedTo is UnitObject or ContainerObject) return;

            result.AddError($"{nameof(DropTableComponent)}'s {nameof(Value.trigger)}: <u><b>{Value.trigger}</b></u> can't be used with <u><b>{attachedTo.GetType().GetNiceName()}</b></u>");
        }

        private void IsDropTableDefined(ValidationResult result)
        {
            // DropTable is required!
            if (Value.dropTable != null) return;

            result.AddError($"{nameof(DropTableComponent)}'s drop table is not defined!");
        }
    }
}