using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;


namespace UnityEngine.UI
{
    [DisallowMultipleComponent]
    [ExecuteAlways]
    public class UXGroup : UIBehaviour
    {
        [SerializeField] private bool m_AllowSwitchOff;
        [SerializeField] private List<UXButton> m_Buttons = new();

        private UXButton _current;

        public UnityEvent<UXButton> onSelectedChanged = new();

        public bool allowSwitchOff
        {
            get => m_AllowSwitchOff;
            set
            {
                m_AllowSwitchOff = value;
                ValidateGroup();
            }
        }

        protected override void Start() => ValidateGroup();

        protected override void OnDestroy()
        {
            foreach (var btn in m_Buttons)
                if (btn)
                    btn.InternalTogSelected = false;
            m_Buttons.Clear();
            base.OnDestroy();
        }

        public void RegisterButton(UXButton button)
        {
            if (!button) return;
            if (m_Buttons.Contains(button)) return;
            m_Buttons.Add(button);

            if (button.InternalTogSelected)
            {
                if (_current && _current != button)
                    _current.InternalTogSelected = false;
                _current = button;
            }

            ValidateGroup();
        }

        public void UnregisterButton(UXButton button)
        {
            if (!button) return;
            m_Buttons.Remove(button);
            if (_current == button)
                _current = null;
            button.InternalTogSelected = false;
        }

        internal void NotifyButtonClicked(UXButton button)
        {
            if (!button) return;

            if (button.InternalTogSelected)
            {
                if (m_AllowSwitchOff) SetSelected(null);
            }
            else
            {
                SetSelected(button);
            }
        }

        private void SetSelected(UXButton target)
        {
            if (_current == target) return;
            var previous = _current;
            _current = null;

            foreach (var btn in m_Buttons)
            {
                bool select = (btn == target);
                if (btn.InternalTogSelected != select)
                    btn.InternalTogSelected = select;
                if (select) _current = btn;
            }

            if (_current) _current.Focus();
            if (previous != _current)
                onSelectedChanged?.Invoke(_current);
        }

        private void ValidateGroup()
        {
            if (_current != null && _current.InternalTogSelected) return;

            if (!m_AllowSwitchOff && m_Buttons.Count > 0)
                SetSelected(m_Buttons[0]);
        }

        public bool AnyOtherSelected(UXButton exclude)
        {
            foreach (var btn in m_Buttons)
                if (btn != exclude && btn.InternalTogSelected)
                    return true;
            return false;
        }

        public void SelectNext() => SelectRelative(1);
        public void SelectPrevious() => SelectRelative(-1);

        private void SelectRelative(int dir)
        {
            if (m_Buttons.Count == 0) return;
            int start = _current ? m_Buttons.IndexOf(_current) : -1;
            int next = FindNextSelectable(start, dir);
            if (next >= 0) SetSelected(m_Buttons[next]);
        }

        private int FindNextSelectable(int startIndex, int dir)
        {
            if (m_Buttons.Count == 0) return -1;
            int count = m_Buttons.Count;
            int index = (startIndex + dir + count) % count;

            for (int i = 0; i < count; i++)
            {
                var btn = m_Buttons[index];
                if (btn && btn.isActiveAndEnabled && btn.Interactable)
                    return index;
                index = (index + dir + count) % count;
            }

            return -1;
        }
    }
}
