#if INPUTSYSTEM_SUPPORT
using System;
using UnityEngine;
using UnityEngine.InputSystem;
using System.Collections.Generic;
using System.Collections;
using AlicizaX.UI;

namespace AlicizaX.UI
{
    internal enum EHotkeyPressType
    {
        Started,
        Performed
    }

    internal static class UXHotkeyRegisterManager
    {
        private readonly struct HotkeyRegistration
        {
            public readonly EHotkeyPressType pressType;
            public readonly UXHotkeyButton button;

            public HotkeyRegistration(UXHotkeyButton btn, EHotkeyPressType pressType)
            {
                button = btn;
                this.pressType = pressType;
            }
        }

        private static readonly Dictionary<string, List<HotkeyRegistration>> _hotkeyRegistry = new(32);


        private static readonly Dictionary<string, (Action<InputAction.CallbackContext> handler, InputActionReference action)> _sharedHandlers =
            new(32);


        private static readonly Dictionary<UXHotkeyButton, string> _buttonRegistrations = new(64);


#if UNITY_EDITOR
        [UnityEditor.Callbacks.DidReloadScripts]
        internal static void ClearHotkeyRegistry()
        {
            foreach (var key in _buttonRegistrations.Keys)
            {
                UnregisterHotkey(key);
            }

            _sharedHandlers.Clear();
            _hotkeyRegistry.Clear();
            _buttonRegistrations.Clear();
        }
#endif

        internal static void RegisterHotkey(UXHotkeyButton button, InputActionReference action, EHotkeyPressType pressType)
        {
            if (action == null || action.action == null || button == null)
                return;

            string actionId = action.action.id.ToString();


            HotkeyRegistration registration = new HotkeyRegistration(button, pressType);


            if (!_hotkeyRegistry.TryGetValue(actionId, out var registrations))
            {
                registrations = new List<HotkeyRegistration>(4);
                _hotkeyRegistry[actionId] = registrations;
            }

            registrations.Add(registration);


            _buttonRegistrations[button] = actionId;

            if (!_sharedHandlers.ContainsKey(actionId))
            {
                Action<InputAction.CallbackContext> handler = ctx => OnHotkeyTriggered(actionId);
                _sharedHandlers[actionId] = (handler, action);

                switch (pressType)
                {
                    case EHotkeyPressType.Started:
                        action.action.started += handler;
                        break;
                    case EHotkeyPressType.Performed:
                        action.action.performed += handler;
                        break;
                }

                action.action.Enable();
            }
        }

        public static void UnregisterHotkey(UXHotkeyButton button)
        {
            if (button == null || !_buttonRegistrations.TryGetValue(button, out var actionId))
                return;


            if (_hotkeyRegistry.TryGetValue(actionId, out var registrations))
            {
                HotkeyRegistration hotkeyInfo;
                for (int i = registrations.Count - 1; i >= 0; i--)
                {
                    if (registrations[i].button == button)
                    {
                        hotkeyInfo = registrations[i];
                        registrations.RemoveAt(i);

                        if (registrations.Count == 0 && _sharedHandlers.TryGetValue(actionId, out var handlerInfo))
                        {
                            var (handler, actionRef) = handlerInfo;
                            if (actionRef != null && actionRef.action != null)
                            {
                                actionRef.action.Disable();
                                _sharedHandlers.Remove(actionId);
                                _hotkeyRegistry.Remove(actionId);

                                switch (hotkeyInfo.pressType)
                                {
                                    case EHotkeyPressType.Started:
                                        actionRef.action.started -= handler;
                                        break;
                                    case EHotkeyPressType.Performed:
                                        actionRef.action.performed -= handler;
                                        break;
                                }
                            }
                        }

                        break;
                    }
                }
            }


            _buttonRegistrations.Remove(button);
        }

        private static void OnHotkeyTriggered(string actionId)
        {
            if (_hotkeyRegistry.TryGetValue(actionId, out var registrations) && registrations.Count > 0)
            {
                var registration = registrations[^1];
                registration.button.HotkeyActionTrigger();
            }
        }
    }
}

public static class UXHotkeyHotkeyExtension
{
    public static void BindHotKey(this UXHotkeyButton button)
    {
        if (button == null) return;


        if (button._hotKeyRefrence != null)
        {
            UXHotkeyRegisterManager.RegisterHotkey(
                button,
                button._hotKeyRefrence,
                button._hotkeyPressType
            );
        }
    }

    public static void UnBindHotKey(this UXHotkeyButton button)
    {
        if (button == null || button._hotKeyRefrence == null) return;
        UXHotkeyRegisterManager.UnregisterHotkey(button);
    }
}
#endif
