using System;
using System.Collections.Generic;
using System.ComponentModel;
using TheGameExtreme.model.card;
using TheGameExtreme.model.@event;
using TheGameExtreme.model.gameActions;

namespace TheGameExtreme.model.manager
{
    public abstract class GameManager: INotifyPropertyChanged
    {

        /* GameMaster implémente un mode de jeu (classe fille de gameMode qui connait les actions a effectué en fonction du mode de jeu */

        protected Parametreur parametreur;
        public Piles ListOrderedStacks { get; set; }
        protected List<Card> CurrentCardPlayed = new List<Card>();
        public String EndMessage { get; set; }
        protected int currentIndexPlayer;


        protected List<Card> currentHand;
        public List<Card> CurrentHand
        {
            get { return currentHand; }
            set
            {
                currentHand = value;
                OnPropertyChanged("CurrentHand");
            }
        }

        #region event

        public event EventHandler<TopRangeChangedEventArgs> TopRangeChanged;
        public event EventHandler<PlayerChangedEventArgs> PlayerChanged;
        public event PropertyChangedEventHandler PropertyChanged;
        public virtual void OnPropertyChanged(string info)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(info));
        }
        public void OnTopRangeChanged(object source, TopRangeChangedEventArgs args)
        {
            TopRangeChanged?.Invoke(this, args);
        }
        protected internal void OnPlayerChanged(object source, PlayerChangedEventArgs args)
        {
            currentIndexPlayer += 1;
            if (currentIndexPlayer == parametreur.players.Count)
            {
                currentIndexPlayer = 0;
            }
            CurrentHand = parametreur.players[currentIndexPlayer].getCardList();
            PlayerChanged?.Invoke(this, new PlayerChangedEventArgs(CurrentHand, parametreur.players[currentIndexPlayer].Pseudo));
            parametreur.GameMode.NbCardAtBeginOfTurn = CurrentHand.Count;
        }

        #endregion



        protected GameManager(Parametreur parametreur)
        {
            this.parametreur = parametreur;

            parametreur.Prepare();

            parametreur.GameMode.TopRangeChanged += OnTopRangeChanged;

            parametreur.GameMode.PlayerChanged += OnPlayerChanged;

            CurrentHand = parametreur.players[0].getCardList();
        }

        

        public void joue(int valueCard, int orderedStackSelected)
        {
            parametreur.GameMode.playCard(valueCard, currentHand, orderedStackSelected, parametreur.players[currentIndexPlayer], CurrentCardPlayed); // Mettre le joueur actif
            EndMessage = parametreur.GameMode.Message;
        }

        public bool endTurn()
        {
            if(parametreur.GameMode.endTurn(currentHand, CurrentCardPlayed, parametreur.players[currentIndexPlayer]))
            {
                EndMessage = parametreur.GameMode.Message;
                if (isEndGame())
                {
                    EndMessage = parametreur.GameMode.Message;
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        private bool isEndGame()
        {
            return parametreur.GameMode.isEndGame(currentHand);
        }




















        //public readonly int nbPlayer;
        //protected int nbMaxCard;
        //protected int currentIndexPlayer;
        //protected List<Player> playerList = new List<Player>();
        //public List<Stack<Card>> ListOrderedStacks { get; set; }
        //protected Deck deck;
        //protected bool win = true;
        //public String EndMessage { get; set; }
        //public List<Card> CurrentHand { get; set; }
        //protected int nbCardAtBeginOfTurn;
        //protected List<Card> CurrentCardPlayed = new List<Card>();
        //protected string langue;
        //public event EventHandler<TopRangeChangedEventArgs> TopRangeChanged;
        //public event EventHandler<PlayerChangedEventArgs> PlayerChanged;


        //protected GameManager(int nbPlayer, List<String> players)
        //{
        //    ListOrderedStacks = new List<Stack<Card>>();
        //    CurrentHand = new List<Card>();

        //    this.nbPlayer = nbPlayer;
        //    players.ForEach(player => playerList.Add(new Player(player)));


        //    initStacks();

        //    initRule();

        //    createDeck();
        //    defineNbMaxCard();
        //    distribueCard();

        //    CurrentHand = playerList[currentIndexPlayer].getCardList();
        //    nbCardAtBeginOfTurn = CurrentHand.Count;
        //}

        //protected void initStacks()
        //{
        //    ListOrderedStacks = new List<Stack<Card>>();

        //    ListOrderedStacks.Add(new Stack<Card>());
        //    ListOrderedStacks.Add(new Stack<Card>());
        //    ListOrderedStacks.Add(new Stack<Card>());
        //    ListOrderedStacks.Add(new Stack<Card>());

        //    for (int i = 0; i < 4; i++)
        //    {
        //        if (i < 2)
        //        {
        //            ListOrderedStacks[i].Push(new ClassicCard(1));
        //        }
        //        else
        //        {
        //            ListOrderedStacks[i].Push(new ClassicCard(100));
        //        }
        //    }
        //}

        //protected void createDeck()
        //{
        //    switch (true)
        //    {
        //        case false:
        //            deck = new ClassicDeck();
        //            break;

        //        default:
        //            deck = new ExtremeDeck();
        //            break;
        //    }
        //}

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

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

        //public void joue(int valueCard, int orderedStackSelected)
        //{
        //    gameMode.playCard(valueCard, CurrentHand, orderedStackSelected, players[0], CurrentCardPlayed); // Mettre le joueur actif
        //}

        //protected void testPossibility(Card card, Stack<Card> orderedStack, bool bottomUp)
        //{
        //    //if (gameMode.checkPlayRule(card, orderedStack, bottomUp, CurrentHand))
        //    //{
        //    //    Card oldCard = orderedStack.Peek();
        //    //    playerList[currentIndexPlayer].joue(card);
        //    //    CurrentCardPlayed.Add(card);
        //    //    orderedStack.Push(card);
        //    //    OnTopRangeChanged(new TopRangeChangedEventArgs(card, oldCard, ListOrderedStacks.IndexOf(orderedStack)));
        //    //    //if (CurrentHand.Count == 0)
        //    //    //{
        //    //    //    endTurn(); // Presque bon, oublie juste d'afficher les nouvelles cartes
        //    //    //}
        //    //}
        //    //else
        //    //{
        //    //    throw new Exception(AppRessource.StrWrongStack);
        //    //}
        //}

        //protected internal void OnTopRangeChanged(TopRangeChangedEventArgs args)
        //{
        //    TopRangeChanged?.Invoke(this, args);
        //}

        //protected internal void OnPlayerChanged(PlayerChangedEventArgs args)
        //{
        //    PlayerChanged?.Invoke(this, args);
        //}

        //public bool isCanPlay()
        //{
        //    if (CurrentHand.Count > 0)
        //    {
        //        return true;
        //    }
        //    else
        //    {
        //        return false;
        //    }
        //}

        //abstract public bool endTurn();

        //abstract protected bool isEndGame();

        //abstract protected void tryToFindSoluce(List<Card> playableCard);

        //abstract protected bool testEndGame(List<Card> playableCard);

        //abstract protected bool effectLose();

        //public int getCurentIndexPlayer()
        //{
        //    return currentIndexPlayer;
        //}

    }
}
