using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace AlicizaX.UI
{
    [DisallowMultipleComponent]
    [AddComponentMenu("Controller/控制器")]
    public sealed class UXController : MonoBehaviour
    {
        [Serializable]
        public class ControllerData
        {
            public string Name = "Controller";
            public int Length = 2;
            [NonSerialized] public int CurrentIndex = 0;
        }

        [SerializeField] private List<ControllerData> _controllers = new List<ControllerData>();

        [SerializeField] private List<UXControllerStateRecorder> _recorders = new List<UXControllerStateRecorder>();

        internal IReadOnlyList<UXControllerStateRecorder> Recorders => _recorders;

        #region Runtime API

        internal IReadOnlyList<ControllerData> Controllers => _controllers;

        private void Awake()
        {
            Initialized();
        }

        private void OnValidate()
        {
            Initialized();
        }

        private void Initialized()
        {
            for (int i = 0; i < _controllers.Count; i++)
            {
                SetControllerIndex(i, 0);
            }
        }

        public ControllerHandle GetController(string name)
        {
            var idx = _controllers.FindIndex(c => c.Name == name);
            if (idx < 0) return null;
            return new ControllerHandle(this, idx);
        }

        internal void SetControllerIndex(int controllerIndex, int selectedIndex)
        {
            if (controllerIndex < 0 || controllerIndex >= _controllers.Count) return;
            var cd = _controllers[controllerIndex];
            if (selectedIndex < 0) selectedIndex = 0;
            if (selectedIndex >= cd.Length) selectedIndex = cd.Length - 1;
            if (cd.CurrentIndex == selectedIndex) return;
            cd.CurrentIndex = selectedIndex;

            foreach (var r in _recorders)
            {
                if (r != null) r.OnControllerIndexChanged(cd.Name, selectedIndex);
            }
        }

        internal bool HasRecorder(UXControllerStateRecorder recorder)
        {
            return _recorders.Find(t => t.ID == recorder.ID) != null;
        }

        #endregion

        [Serializable]
        public class ControllerHandle
        {
            private readonly UXController _owner;
            private readonly int _controllerIndex;

            public ControllerHandle(UXController owner, int controllerIndex)
            {
                _owner = owner;
                _controllerIndex = controllerIndex;
            }

            public int SelectedIndex
            {
                get
                {
                    if (_controllerIndex < 0 || _controllerIndex >= _owner._controllers.Count) return 0;
                    return _owner._controllers[_controllerIndex].CurrentIndex;
                }
                set { _owner.SetControllerIndex(_controllerIndex, value); }
            }

            public int Length
            {
                get
                {
                    if (_controllerIndex < 0 || _controllerIndex >= _owner._controllers.Count) return 0;
                    return _owner._controllers[_controllerIndex].Length;
                }
            }

            public string Name => (_controllerIndex >= 0 && _controllerIndex < _owner._controllers.Count) ? _owner._controllers[_controllerIndex].Name : null;
        }
    }
}
