using CoreLibrary.Core;
using CoreLibrary.Events;
using CoreLibrary.Joueurs;
using CoreLibrary.Regles;
namespace CoreLibrary
{
///
/// Représente une partie de jeu.
///
public class Partie
{
private readonly IRegles regles;
///
/// Définit le délégué pour gérer les événements avec des arguments de type string.
///
public delegate string? StringEventHandler(Object? sender, TEventArgs e);
///
/// Définit le délégué pour gérer les événements avec des arguments de type Jeton.
///
public delegate Jeton? JetonEventHandler(Object? sender, TEventArgs e);
///
/// Événement déclenché lorsqu'il est nécessaire de d'ajouter un joueur.
///
public event StringEventHandler? DemanderJoueur;
///
/// Événement déclenché lorsqu'il est nécessaire d'ajouter un jeton.
///
public event JetonEventHandler? DemanderJeton;
///
/// Événement déclenché lorsqu'il est nécessaire d'ajouter un joueur.
///
public event EventHandler? AjouterJoueur;
///
/// Événement déclenché lorsqu'une partie commence.
///
public event EventHandler? DebutPartie;
///
/// Événement déclenché lorsqu'un nouveau tour commence.
///
public event EventHandler? NouveauTour;
///
/// Événement déclenché lorsqu'il est nécessaire d'ajouter un jeton.
///
public event EventHandler? AjouterJeton;
///
/// Événement déclenché lorsqu'un jeton est supprimé.
///
public event EventHandler? SupprimerDernierJeton;
///
/// Événement déclenché lorsqu'un code est ajouté.
///
public event EventHandler? AjouterCode;
///
/// Événement déclenché lorsque la main est passée au joueur suivant.
///
public event EventHandler? PasserMain;
///
/// Événement déclenché lorsque la partie est terminée.
///
public event EventHandler? PartieTerminee;
///
/// Méthode pour déclencher l'événement de demande d'ajout d'un joueur.
///
/// Le numéro du joueur à ajouter
/// Le nom du joueur demandé
private string? QuandDemanderJoueur(int numero) => DemanderJoueur?.Invoke(this, new DemanderJoueurEventArgs(numero));
///
/// Méthode pour déclencher l'événement de demande d'ajout d'un jeton.
///
/// Le jeton demandé
private Jeton? QuandDemanderJeton(int indice) => DemanderJeton?.Invoke(this, new DemanderJetonEventArgs(indice));
///
/// Méthode pour déclencher l'événement d'ajout d'un joueur.
///
/// Le joueur à ajouter.
private void QuandAjouterJoueur(Joueur joueur) => AjouterJoueur?.Invoke(this, new AjouterJoueursEventArgs(joueur));
///
/// Méthode pour déclencher l'événement du début d'un partie.
///
private void QuandDebutPartie() => DebutPartie?.Invoke(this, new DebutPartieEventArgs());
///
/// Méthode pour déclencher l'événement d'un nouveau tour.
///
/// Le joueur dont c'est le tour.
/// Le numéro du tour.
/// La grille de jeu.
/// Les indicateurs de jeu.
private void QuandNouveauTour(Joueur joueur, int tour, IEnumerable> grille, IEnumerable> indicateurs) => NouveauTour?.Invoke(this, new NouveauTourEventArgs(joueur, tour, grille, indicateurs));
///
/// Méthode pour déclencher l'événement d'ajout d'un nouveau jeton.
///
/// Le jeton à ajouter.
private void QuandNouveauJeton(Jeton jeton) => AjouterJeton?.Invoke(this, new AjouterJetonEventArgs(jeton));
///
/// Méthode pour déclencher l'événement de suppression du dernier jeton du code.
///
private void QuandSupprimerDernierJeton() => SupprimerDernierJeton?.Invoke(this, new SupprimerDernierJetonEventArgs());
///
/// Méthode pour déclencher l'événement d'ajout d'un nouveau code.
///
/// Le code à ajouter.
private void QuandNouveauCode(Code code) => AjouterCode?.Invoke(this, new AjouterCodeEventArgs(code));
///
/// Méthode pour déclencher l'événement de passage de la main au joueur suivant.
///
private void QuandPasserMain() => PasserMain?.Invoke(this, new PasserMainEventArgs());
///
/// Méthode pour déclencher l'événement de fin de partie.
///
/// La liste des joueurs gagnants.
/// La liste des joueurs perdants.
private void QuandPartieTerminee(IEnumerable gagnants, IEnumerable perdants) => PartieTerminee?.Invoke(this, new PartieTermineeEventArgs(gagnants, perdants));
///
/// Crée une nouvelle instance de la classe Partie.
///
/// Les règles de la partie.
public Partie(IRegles regles)
{
this.regles = regles;
}
///
/// Lance le déroulement de la partie.
///
public void Jouer()
{
/// Ajout des joueurs jusqu'à atteindre le nombre maximum de joueurs défini par les règles
AjouterJoueurs();
regles.CommencerLaPartie();
QuandDebutPartie();
// Boucle principale du jeu qui dure jusqu'à qu'une condition de fin soit déclenchée
while (!regles.EstTerminee())
{
Joueur joueurCourant = regles.JoueurCourant();
Plateau plateauCourant = joueurCourant.Plateau;
QuandNouveauTour(joueurCourant, plateauCourant.Tour, plateauCourant.Grille(), plateauCourant.Indicateurs());
Code code = regles.GenererCode();
CreerCode(code);
// Phase de saisie du code par le joueur jusqu'à que le code soit complet.
plateauCourant.AjouterCode(code);
QuandNouveauCode(code);
regles.PasserLaMain();
QuandPasserMain();
}
regles.Gagnants();
regles.Perdants();
QuandPartieTerminee(regles.Gagnants(), regles.Perdants());
}
private void AjouterJoueurs()
{
while (regles.NbJoueurs != regles.NbJoueursMaximum)
{
string nom = QuandDemanderJoueur(regles.NbJoueurs + 1) ?? $"Joueur {regles.NbJoueurs + 1}";
Joueur joueur = regles.AjouterJoueur(nom);
QuandAjouterJoueur(joueur);
}
}
private void CreerCode(Code code)
{
while (!code.EstComplet())
{
Jeton? jeton = QuandDemanderJeton(code.NbJetons);
if (DemanderJeton == null)
{
jeton = new Jeton();
}
if(!jeton.HasValue)
{
code.SupprimerDernierJeton();
QuandSupprimerDernierJeton();
}
else
{
code.AjouterJeton(jeton.Value);
QuandNouveauJeton(jeton.Value);
}
}
}
}
}