using System;
using System.Collections.Generic;
using FairyGUI;
using UnityEngine;

namespace NBF
{
    public class ListSelector
    {
        private GList _list;
        private readonly List<Type> _ignores = new List<Type>();
        // private readonly List<GObject> _items = new List<GObject>();

        private float itemWidth = 200f;
        private float itemHeight = 180f;

        public object SelectedItem => _list.selectedIndex > 0 ? _list.GetChildAt(_list.selectedIndex) : null;

        public ListSelector(GList list, params Type[] ignores)
        {
            _list = list;
            if (ignores != null && ignores.Length > 0)
            {
                _ignores.AddRange(ignores);
            }
        }

        #region 数据刷新

        public void Refresh()
        {
            var children = _list.GetChildren();
            foreach (var item in children)
            {
                if (_ignores.Contains(item.GetType())) continue;
                itemWidth = item.width;
                itemHeight = item.height;
                break;
            }
        }

        #endregion

        #region 操作

        public void Up()
        {
            Move(Vector2.up);
        }

        public void Down()
        {
            Move(Vector2.down);
        }

        public void Right()
        {
            Move(Vector2.right);
        }

        public void Left()
        {
            Move(Vector2.left);
        }

        public void Move(Vector2 direction)
        {
            if (_list.selectedIndex == -1)
            {
                // 首次选择第一个可选中项
                SelectFirstSelectable();
                return;
            }

            var currentPos = GetItemPosition(_list.selectedIndex);
            var nearestIndex = FindNearestSelectableItem(currentPos, direction);

            // 如果是左右移动且未找到目标，则尝试寻找前一个或后一个可选项
            if (nearestIndex == -1 && (direction == Vector2.left || direction == Vector2.right))
            {
                if (direction == Vector2.left)
                {
                    // 寻找前一个可选项
                    nearestIndex = FindPreviousSelectableItem(_list.selectedIndex);
                }
                else if (direction == Vector2.right)
                {
                    // 寻找后一个可选项
                    nearestIndex = FindNextSelectableItem(_list.selectedIndex);
                }
            }

            if (nearestIndex != -1)
            {
                SetSelection(nearestIndex);
            }
        }

        #endregion

        #region 内部方法

        private Vector2 GetItemPosition(int index)
        {
            var item = _list.GetChildAt(index);
            return item.position;
        }

        private int FindNearestSelectableItem(Vector2 fromPos, Vector2 direction)
        {
            var bestIndex = -1;
            var bestDistance = float.MaxValue;

            for (var i = 0; i < _list.numItems; i++)
            {
                if (!IsSelectableItem(i)) continue;

                var targetPos = GetItemPosition(i);
                var diff = targetPos - fromPos;

                // 检查方向匹配度
                if (IsDirectionMatch(direction, diff))
                {
                    var distance = Vector2.Distance(fromPos, targetPos);
                    if (distance < bestDistance && distance > 0.1f)
                    {
                        bestDistance = distance;
                        bestIndex = i;
                    }
                }
            }

            return bestIndex;
        }

        private int FindPreviousSelectableItem(int currentIndex)
        {
            for (int i = currentIndex - 1; i >= 0; i--)
            {
                if (IsSelectableItem(i))
                    return i;
            }

            return -1;
        }

        private int FindNextSelectableItem(int currentIndex)
        {
            for (int i = currentIndex + 1; i < _list.numItems; i++)
            {
                if (IsSelectableItem(i))
                    return i;
            }

            return -1;
        }

        private bool IsDirectionMatch(Vector2 direction, Vector2 diff)
        {
            if (direction == Vector2.up)
                return diff.y < 0 && Mathf.Abs(diff.x) < itemWidth; // 修正：向上应该是Y值更小
            if (direction == Vector2.down)
                return diff.y > 0 && Mathf.Abs(diff.x) < itemWidth; // 修正：向下应该是Y值更大
            if (direction == Vector2.left)
                return diff.x < 0 && Mathf.Abs(diff.y) < itemHeight;
            if (direction == Vector2.right)
                return diff.x > 0 && Mathf.Abs(diff.y) < itemHeight;
            return false;
        }

        private bool IsSelectableItem(int index)
        {
            var item = _list.GetChildAt(index);
            var ret = !_ignores.Contains(item.GetType());
            if (item.GetType() == typeof(ListTitleItem))
            {
            }

            return ret;
        }

        private void SelectFirstSelectable()
        {
            for (var i = 0; i < _list.numItems; i++)
            {
                if (IsSelectableItem(i))
                {
                    SetSelection(i);
                    break;
                }
            }
        }

        private void SetSelection(int index)
        {
            _list.selectedIndex = index;
            _list.ScrollToView(index, true);
        }

        #endregion
    }
}