using System.Linq;
using Sirenix.OdinInspector.Editor.Validation;
using UnityEngine;
using VOID.Editor.AttributeValidator;
using VOID.ScriptableObjects.Animations;

[assembly: RegisterValidator(typeof(AnimationListValidator))]

namespace VOID.Editor.AttributeValidator
{
    public class ActionAnimationListValidator : ValueValidator<ActionAnimationList>
    {
        private static readonly string[] SimpleEvents = { "OnStart", "OnPerform", "OnEnd" };
        
        protected override void Validate(ValidationResult result)
        {
            if (Value == null) return;
            
            ValidateClipEvents(result, Value.list.clip, SimpleEvents);
        }

        private void ValidateClipEvents(ValidationResult result, AnimationClip clip, string[] neededEvents)
        {
            if (!clip) return;
            
            var currentEvents = clip.events.Select(ev => ev.functionName).ToList();
            var missingEvents = neededEvents.Except(currentEvents).ToList();
            var invalidEvents = currentEvents.Except(neededEvents).ToList();
            var duplicatedEvents = currentEvents.GroupBy(s => s).Where(g => g.Count() > 1).Select(g => g.Key).ToList();
            
            if (missingEvents.Count > 0)
            {
                var missingEventsText = string.Join(" ", missingEvents.Select(str => $"<u>{str}</u>"));
                result
                    .AddError($"<u>{clip.name}</u> is missing required events: " + missingEventsText)
                    .SetSelectionObject(clip);
            }
            
            if (invalidEvents.Count > 0)
            {
                var invalidEventsText = string.Join(" ", invalidEvents.Select(str => $"<u>{str}</u>"));
                result
                    .AddWarning($"<u>{clip.name}</u> contain unknown events: " + invalidEventsText)
                    .SetSelectionObject(clip);
            }

            if (duplicatedEvents.Count > 0)
            {
                var duplicatedEventsText = string.Join(" ", duplicatedEvents.Select(str => $"<u>{str}</u>"));
                result
                    .AddError($"<u>{clip.name}</u> contain duplicated events: " + duplicatedEventsText)
                    .SetSelectionObject(clip);
            }
        }
    }
}