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

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;
        protected List<Card> CurrentCardPlayed = new List<Card>();
        public string EndMessage { get; set; }
        protected int currentIndexPlayer;
        protected List<Card> currentHand;
        protected bool win;
        public List<Card> CurrentHand
        {
            get { return currentHand; }
            set
            {
                currentHand = value;
                OnPropertyChanged("CurrentHand");
            }
        }

        #region event

        public event EventHandler<EventArgs> EndGame;
        public event EventHandler<PlayerChangedEventArgs> PlayerChanged;
        public event PropertyChangedEventHandler PropertyChanged;
        public virtual void OnPropertyChanged(string info)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(info));
        }
        public void OnEndGame(object source, EventArgs args)
        {
            EndGame?.Invoke(source, args);
        }
        protected internal void OnPlayerChanged(object source, PlayerChangedEventArgs args)
        {
            currentIndexPlayer += 1;
            if (currentIndexPlayer == parametreur.players.Count)
            {
                currentIndexPlayer = 0;
            }
            CurrentHand = parametreur.players[currentIndexPlayer].getCardList();
            int i = 0;
            while (CurrentHand.Count == 0 && i != 5)
            {
                currentIndexPlayer += 1;
                if (currentIndexPlayer == parametreur.players.Count)
                {
                    currentIndexPlayer = 0;
                }
                CurrentHand = parametreur.players[currentIndexPlayer].getCardList();
                i++; // Garde fou
            }
            if (i == 5)
            {
                EndMessage = AppRessource.StrWin;
                win = true;
            }
            else
            {
                parametreur.GameMode.TestEndGame(CurrentHand);
                PlayerChanged?.Invoke(source, new PlayerChangedEventArgs(CurrentHand, parametreur.players[currentIndexPlayer].Pseudo));
                parametreur.GameMode.NbCardAtBeginOfTurn = CurrentHand.Count;
            }
        }

        #endregion



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

            parametreur.Prepare();

            parametreur.GameMode.EndGame += OnEndGame;

            parametreur.GameMode.PlayerChanged += OnPlayerChanged;

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

        

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

        public bool endTurn()
        {
            if(parametreur.GameMode.endTurn(currentHand, CurrentCardPlayed, parametreur.players[currentIndexPlayer]))
            {
                EndMessage = parametreur.GameMode.Message + "Il vous restait " + parametreur.GameMode.getScore() + " cartes à jouer!";
                return true;
            }
            else
            {
                EndMessage = parametreur.GameMode.Message;
                if (win)
                {
                    OnEndGame(this, new EventArgs());
                    return true;
                }
                return false;
            }
        }

        public Piles getPiles()
        {
            return parametreur.GameMode.Piles;
        }
    }
}
