using System;
using System.Collections.Generic;
using System.Linq;
using GameMessage;

namespace GameFix.Poker
{
    public static class CardListExtensions
    {
        public static void Sort(this List<Card> cards, CardStyleInfo cardStyleInfo)
        {
            if (cardStyleInfo == null) return;
            if (cardStyleInfo.CardStyle == DataCardConst.CardStyle331
                || cardStyleInfo.CardStyle == DataCardConst.CardStyle332
                || cardStyleInfo.CardStyle == DataCardConst.CardStyle3311)
            {
                 var sortCards = cards.GroupBy(c => c.Value)
                     .OrderBy(x => x.Key).Select(g => g.ToList()).ToList();
                 var tmpCards = new List<Card>();
                 cards.Clear();
                 for (int i = 0; i < sortCards.Count; i++)
                 {
                     if (sortCards[i].Count >= 3)
                     {
                         cards.AddRange(sortCards[i].GetRange(0, 3));
                         sortCards[i].RemoveRange(0,3);
                     }
                     tmpCards.AddRange(sortCards[i]);
                 }
                 cards.AddRange(tmpCards);
            }   
            else
            {
                cards.Sort(new CardStyleComparer(cardStyleInfo));
            }
        }
        
        public static string PrintCards(this IEnumerable<Card> cards)
        {
            var str = string.Join(",", cards);
            return str;
        }
        
#if Server || UNITY_EDITOR
        /// <summary>
        ///  字符转成Card数组 （主要调试用）
        /// </summary>
        ///
        public static List<Card> ToCardList(this string cardString, Deck deck) {
            var segment = cardString.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            var list = new List<Card>();
            foreach (var item in segment)
            {
                var (suit, value) = CardManager.GetSuitValueFromStr(item);
                var card = deck.GetCard(suit, value);
                if (card != null)
                    list.Add(card);
            }

            return list;
        }
#endif

        public static void RandomList<T>(this List<T> list)
        {
            Random rd = new Random();
            for (int i = 0; i < list.Count; i++)
            {
                int idx = rd.Next(0, list.Count);
                if (idx != i)
                    (list[i],list[idx]) = (list[idx], list[i]);
            }
        }
        
        /// <summary>
        /// 判断元素是否都一致
        /// </summary>
        public static bool AllElementsSame<T>(this IEnumerable<T> enumerable)
        {
            if (enumerable == null)
                throw new ArgumentNullException(nameof(enumerable));

            // 如果集合为空，直接返回 true
            using (var enumerator = enumerable.GetEnumerator())
            {
                if (!enumerator.MoveNext())
                    return true;

                // 获取第一个元素作为参照
                T first = enumerator.Current;
                var comparer = EqualityComparer<T>.Default;
                // 遍历后续元素进行比较
                while (enumerator.MoveNext())
                {
                    if (!comparer.Equals(first, enumerator.Current))
                        return false;
                }

                return true;
            }
        }

        
        /// <summary>
        /// 交换两个列表中的元素（按索引交换）
        /// </summary>
        /// <typeparam name="T">元素类型</typeparam>
        /// <param name="list1">第一个列表</param>
        /// <param name="list2">第二个列表</param>
        /// <param name="count">交换数量，不传则交换 min(list1.Count, list2.Count)</param>
        public static void Switch<T>(this List<T> list1, List<T> list2, int count = -1)
        {
            if (list1 == null || list2 == null) return;

            if (count < 0)
                count = Math.Min(list1.Count, list2.Count);

            for (int i = 0; i < count && i < list1.Count && i < list2.Count; i++)
            {
                (list1[i], list2[i]) = (list2[i], list1[i]);
            }
        }

        /// <summary>
        /// 交换两个列表中指定的元素
        /// </summary>
        /// <typeparam name="T">元素类型</typeparam>
        /// <param name="list1">第一个列表</param>
        /// <param name="list2">第二个列表</param>
        /// <param name="items1">要从list1交换出去的元素</param>
        /// <param name="items2">要从list2交换出去的元素（可选，不传则从list2前部取items1.Count个元素）</param>
        public static void Switch<T>(this List<T> list1, List<T> list2, List<T> items1, List<T> items2 = null)
        {
            if (list1 == null || list2 == null) return;
            if (items1 == null) return;

            // 如果items2为空，从list2前部取与items1数量相同的元素
            if (items2 == null)
            {
                int count = Math.Min(items1.Count, list2.Count);
                items2 = list2.GetRange(0, count);
            }

            // 从list1移除items1，添加items2
            foreach (var item in items1)
            {
                list1.Remove(item);
            }
            list1.AddRange(items2);

            // 从list2移除items2，添加items1
            foreach (var item in items2)
            {
                list2.Remove(item);
            }
            list2.AddRange(items1);
        }

    }
}