using System;
using KitsuneCafe.System.Attributes;
using Unity.Properties;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;

[CustomPropertyDrawer(typeof(ConditionalDisplayAttribute), true)]
public class ConditionalDisplayPropertyDrawer : PropertyDrawer
{
    public override VisualElement CreatePropertyGUI(SerializedProperty property)
    {
        var attribute = this.attribute as ConditionalDisplayAttribute;
        var serializedObject = property.serializedObject;
        var names = attribute.Properties;
        var length = names.Length;
        var properties = new SerializedProperty[length];

        for (int i = 0; i < length; i++)
        {
            properties[i] = serializedObject.FindProperty(names[i]);
        }

        return new BoolConditionPropertyField(properties, attribute, property);
    }

    public abstract class ConditionalPropertyField : PropertyField
    {
        protected readonly SerializedProperty[] properties;
        protected readonly ConditionalDisplayAttribute attribute;

        public ConditionalPropertyField(SerializedProperty[] properties, ConditionalDisplayAttribute attribute, SerializedProperty property) : base(property)
        {
            this.properties = properties;
            this.attribute = attribute;
            TrackProperties(properties);
        }

        public ConditionalPropertyField(SerializedProperty[] properties, ConditionalDisplayAttribute attribute, SerializedProperty property, string label) : base(property, label)
        {
            this.properties = properties;
            this.attribute = attribute;
            TrackProperties(properties);
        }

        private void TrackProperties(SerializedProperty[] properties)
        {
            var len = properties.Length;
            for (int i = 0; i < len; i++)
            {
                var property = properties[i];
                OnTrackedValueChanged(property);
                this.TrackPropertyValue(property, OnTrackedValueChanged);
            }
        }

        protected abstract void OnTrackedValueChanged(SerializedProperty property);
    }

    public class BoolConditionPropertyField : ConditionalPropertyField
    {
        public BoolConditionPropertyField(SerializedProperty[] properties, ConditionalDisplayAttribute attribute, SerializedProperty property) : base(properties, attribute, property)
        {
        }

        public BoolConditionPropertyField(SerializedProperty[] properties, ConditionalDisplayAttribute attribute, SerializedProperty property, string label) : base(properties, attribute, property, label)
        {
        }

        protected override void OnTrackedValueChanged(SerializedProperty property)
        {
            var value = (attribute.LogicalOperator, attribute.ComparisonOperator) switch
            {
                (LogicalOperator.Or, ComparisonOperator.Equal) => true,
                (LogicalOperator.And, ComparisonOperator.NotEqual) => true,
                _ => false
            };

            for (int i = 0; i < properties.Length; i++)
            {
                if (properties[i].boolValue == value)
                {
                    DisplayElement(value);
                    return;
                }
            }

            DisplayElement(!value);
        }

        private void DisplayElement(bool displayed)
        {
            style.display = displayed ? DisplayStyle.Flex : DisplayStyle.None;
        }
    }
}


