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

namespace GameFix.Poker
{
    public abstract class CardBaseGroup
    {
        // key-牌值 value-牌组信息 (不含癞子)
        protected List<CardGroupList> mCardGroupList = new List<CardGroupList>(20); // 大王19 （按照牌值合并的牌组）
        // key-牌数量 value-这个数量对应的所有牌组 (不含癞子)
        protected Dictionary<int, List<CardGroupList>> mCardGroupDic;

        protected List<Card> mCards; // 原始的牌数据
        protected List<Card> mLZCards; // 癞子牌
        protected List<Card> mNoLZCards;// 除去癞子的牌列表

        internal IStyleComparer mStyleComparer;
        internal Deck mDeck;
        protected List<CardStyleBaseHelper> mCardStyleBaseHelpers = new List<CardStyleBaseHelper>();

        public List<Card> SelfCards => mCards;
        public List<CardGroupList> SelfCardGroupList => mCardGroupList;
        public Dictionary<int, List<CardGroupList>> SelfCardGroupDic => mCardGroupDic;

        public List<Card> Cards
        {
            get
            {
                // 如果是手牌对象
                if (this is CardHandGroup cardHandGroup)
                {
                    // 并且有需要检测得牌，就取CheckCardGroup得牌
                    if (cardHandGroup.CheckCardGroup?.mCards.Count > 0)
                        return cardHandGroup.CheckCardGroup.mCards;
                }
                return mCards;
            }
        }

        public List<Card> LZCards
        {
            get
            {
                // 如果是手牌对象
                if (this is CardHandGroup cardHandGroup)
                {
                    // 并且有需要检测得牌，就取CheckCardGroup得牌
                    if (cardHandGroup.CheckCardGroup?.mLZCards.Count > 0)
                        return cardHandGroup.CheckCardGroup.mLZCards;
                }
                return mLZCards;
            }
        }
        
        public List<Card> NoLZCards
        {
            get
            {
                // 如果是手牌对象
                if (this is CardHandGroup cardHandGroup)
                {
                    // 并且有需要检测得牌，就取CheckCardGroup得牌
                    if (cardHandGroup.CheckCardGroup?.mNoLZCards.Count > 0)
                        return cardHandGroup.CheckCardGroup.mNoLZCards;
                }
                return mNoLZCards;
            }
        }
        
        public List<CardGroupList> CardGroupList
        {
            get
            {
                // 如果是手牌对象
                if (this is CardHandGroup cardHandGroup)
                {
                    // 并且有需要检测得牌，就取CheckCardGroup得牌
                    if (cardHandGroup.CheckCardGroup?.mCardGroupList.Count > 0)
                        return cardHandGroup.CheckCardGroup.mCardGroupList;
                }
                return mCardGroupList;
            }
        }
        
        public Dictionary<int, List<CardGroupList>> CardGroupDic
        {
            get
            {
                // 如果是手牌对象
                if (this is CardHandGroup cardHandGroup)
                {
                    // 并且有需要检测得牌，就取CheckCardGroup得牌
                    if (cardHandGroup.CheckCardGroup?.mCardGroupDic.Count > 0)
                        return cardHandGroup.CheckCardGroup.mCardGroupDic;
                }
                return mCardGroupDic;
            }
        }
        
        protected CardBaseGroup(IEnumerable<Card> cards, Deck deck)
        {
            mDeck = deck;
            mCards = new List<Card>(cards);
            mCards.Sort(new CardDefaultComparer(true));
            mLZCards = new List<Card>(mCards.Count);
            mNoLZCards = new List<Card>(mCards.Count);
            InitPreData();
        }

        void InitPreData()
        {
            mCardGroupList.Clear();
            mLZCards.Clear();
            mNoLZCards.Clear();
            for (int i = 0; i < mCardGroupList.Capacity; i++)
            {
                mCardGroupList.Add(new CardGroupList());
            }
            
            for (int i = 0; i < mCards.Count; i++)
            {
                if (mCards[i].CardType == DataCardConst.CardTypeLZ)
                {
                    mLZCards.Add(mCards[i]);
                    continue;
                }
                
                mCardGroupList[mCards[i].Value].Add(mCards[i]);
                mNoLZCards.Add(mCards[i]);
            }
            
            mCardGroupDic = mCardGroupList
                .GroupBy(g=>g.Count)
                .Where(g=>g.Key != 0)
                .ToDictionary(g=>g.Key, g=>g.ToList());
        }

        internal CardBaseGroup RegisterHelper(List<CardStyleBaseHelper> helpers)
        {
            mCardStyleBaseHelpers.AddRange(helpers);
            return this;
        }
        
        internal CardBaseGroup RegisterStyleComparer(IStyleComparer comparer)
        {
            mStyleComparer = comparer;
            return this;
        }

        public CardBaseGroup RemoveCards(IEnumerable<Card> cards)
        {
            mCards.RemoveAll(cards.Contains);
            InitPreData();
            return this;
        }
        
        public CardBaseGroup RemoveCards(IEnumerable<CardGroupList> cardGroups)
        {
            var cards = cardGroups.SelectMany(x => x).ToList();
            RemoveCards(cards);
            return this;
        }
        
        public CardBaseGroup AddHelper(CardStyleBaseHelper helper)
        {
            mCardStyleBaseHelpers.Add(helper);
            return this;
        }

        /// <summary>
        /// 获取一种牌型的数量
        /// </summary>
        /// <returns>数量</returns>
        public int GetSingleCardStyleCount(int cardValue)
        {
            if (cardValue >= mCardGroupList.Capacity)
                return 0;
            return mCardGroupList[cardValue].Count;
        }

        public CardGroupList GetAllJoker()
        {
            CardGroupList list = new CardGroupList();
            list.AddRange(mCardGroupList[DataCardConst.CardValueBigJoker]);
            list.AddRange(mCardGroupList[DataCardConst.CardValueSmallJoker]);
            return list;
        }

        public bool HaveJoker()
        {
            return mCards.Any(x => DataCardConst.JokerValues.Contains(x.Value));
        }

        public int GetJokerCount()
        {
            return mCards.Count(x => DataCardConst.JokerValues.Contains(x.Value));
        }
        
        public bool IsAllJoker()
        {
            return CardFunc.IsAllJoker(mCards);
        }
        
        public bool IsAllSuitSame()
        {
            return CardFunc.IsAllSuitSame(mCards);
        }
        
        public bool IsAllValueSame()
        {
            return CardFunc.IsAllValueSame(mCards);
        }

        protected CardStyleBaseHelper GetHelper(int cardStyle)
        {
            return mCardStyleBaseHelpers.Find(x => x.CardStyle == cardStyle);
        }
    }
}