using System;
using System.Collections.Generic;
using OrderStacks.model.card;
using OrderStacks.model.deck;
using OrderStacks.model.@event;
using OrderStacks.model.piles;

namespace OrderStacks.model.gameActions.abstractRules
{
    public abstract class GameMode
    {
        protected List<GameAction> gameActions;
        public Piles Piles { get; protected set; }
        public int NbCardAtBeginOfTurn { get; set; }
        protected Deck deck;
        protected int nbMaxCard;
        protected bool end;
        public string Message { get; set; } = "";


        #region

        public event EventHandler<EventArgs> EndGame;
        public event EventHandler<PlayerChangedEventArgs> PlayerChanged;
        protected internal void OnEndGame(EventArgs args)
        {
            EndGame?.Invoke(this, args);
        }
        protected internal void OnPlayerChanged(PlayerChangedEventArgs args)
        {
            PlayerChanged?.Invoke(this, args);
        }

        #endregion


        protected GameMode(Piles piles, Deck deck)
        {
            gameActions = new List<GameAction>();
            Piles = piles;
            this.deck = deck;
        }

        public abstract void load(int nbPlayer, List<Player> players);

        protected void defineNbMaxCard(int nbPlayer)
        {
            switch (nbPlayer)
            {
                case 1:
                    nbMaxCard = 8;
                    NbCardAtBeginOfTurn = 8;
                    break;
                case 2:
                    nbMaxCard = 7;
                    NbCardAtBeginOfTurn = 7;
                    break;
                default:
                    nbMaxCard = 6;
                    NbCardAtBeginOfTurn = 6;
                    break;
            }
        }

        protected void quickSort(List<Card> ar, int start, int end)
        {
            if (start < end)
            {
                Card pivot = ar[end];
                int pIndex = start;
                Card swap;

                for (int i = start; i < end; i++)
                {
                    if (ar[i].Value.CompareTo(pivot.Value) < 0)
                    {
                        swap = ar[pIndex];
                        ar[pIndex] = ar[i];
                        ar[i] = swap;
                        pIndex++;
                    }
                }

                ar[end] = ar[pIndex];
                ar[pIndex] = pivot;

                quickSort(ar, start, pIndex - 1);
                quickSort(ar, pIndex + 1, end);
            }
        }

        protected void distribueCard(List<Player> players)
        {
            players.ForEach(player =>
            {
                for (int i = 0; i < nbMaxCard; i++)
                {
                    int r = new Random().Next(0, deck.size() - 1);
                    player.pioche(deck.getCard(r));
                    deck.removeAt(r);
                }
                List<Card> cards = player.getCardList();
                quickSort(cards, 0, cards.Count - 1);
            });
        }

        public abstract void pioche(List<Card> currentHand, Player player);

        public abstract bool playCard(decimal valueCard, List<Card> currentHand, int orderedStackSelected, Player player, List<Card> CurrentCardPlayed);

        public abstract bool endTurn(List<Card> currentHand, List<Card> CurrentCardPlayed, Player player);

        public abstract void TestEndGame(List<Card> currentHand);

        public int getScore()
        {
            return deck.size();
        }
    }
}
