class Jeu {

    public final String jouerAction(Action ja) {
        Joueur j = mesJoueurs.get(ja.getIdJoueur());
        Carte c = j.getDeckMain().get(ja.getNumeroCarte());
        StringBuilder desc = new StringBuilder();
        boolean gratuit = false;
        Carte carteGratuite = c;
        for (int k = 0; k < (j.getDeckPlateau().size() - 1); k++) {
            if (j.getDeckPlateau().get(k).getBatimentSuivant() == c.getNom()) {
                carteGratuite = j.getDeckPlateau().get(k);
                gratuit = true;
            }
        }
        switch (ja.getType()) {

        case DefausserCarte:
            c = j.defausserCarte(ja.getNumeroCarte());
            desc.append("Le joueur " + ja.getIdJoueur() + " a défaussé la carte " + Couleur.consoleColor(c.getCouleur()) + c.getNom());
            tabDeck.get(this.age - 1).add(c);
            break;

        case AcheterRessource:
            if (!gratuit) {
                int idJoueurAPayer = (ja.getIdJoueur() + ja.getNumVoisin()) % mesJoueurs.size();

                if (idJoueurAPayer < 0)
                    idJoueurAPayer = mesJoueurs.size() - 1;

                int montantPaiement = 2;
                EffetCommercial ec = c.getEffetCommercial();
                if (ec != null && ((ec == ACHAT_MATIERE_DROITE && ja.getNumVoisin() == 1) || (ec == ACHAT_MATIERE_GAUCHE && ja.getNumVoisin() == -1) || (ec == ACHAT_PREMIERE))) {
                    montantPaiement = 1;
                    desc.append("Grâce à un effet commercial, le joueur " + ja.getIdJoueur() + " a acheté des ressources à coût réduits ");
                } else {
                    desc.append("Le joueur " + ja.getIdJoueur() + " a acheté des ressources");
                }
                desc.append(" au joueur " + idJoueurAPayer + "\n");
                mesJoueurs.get(idJoueurAPayer).recevoirPaiement(j.payer(montantPaiement));
            }

        case PoserCarte:
            c = j.poserCarte(ja.getNumeroCarte());
            desc.append("Le joueur " + ja.getIdJoueur() + " a posé la carte " + Couleur.consoleColor(c.getCouleur()) + c.getNom());
            if (gratuit) {
                desc.append(WHITE + " gratuitement grâce à la carte ");
                desc.append(Couleur.consoleColor(carteGratuite.getCouleur()) + carteGratuite.getNom());
            } else {
                ArrayList<Ressource> cr = c.getCoutRessources();
                if (cr.size() > 0) {
                    desc.append(WHITE + " qui coûte ");
                    HashMap<Ressource, Integer> hr = new HashMap<Ressource, Integer>();

                    for (Ressource r : cr)
                        hr.put(r, hr.get(r) == null ? 1 : hr.get(r) + 1);

                    for (Ressource r : hr.keySet())
                        desc.append(hr.get(r) + " de " + r.toString() + ", ");

                    desc.setLength(desc.length() - 2);
                }

                EffetCommercial ec = c.getEffetCommercial();
                int pieceBonus = 0;
                if (ec != null) {
                    desc.append("\n Grâce à un effet commercial, le joueur reçoit ");
                    switch (ec) {
                    case BONUS_OR:
                        j.recevoirPaiement(5);
                        desc.append("5 pièces d'or\n");
                        break;

                    case OR_CARTE_MARRON:
                        for (Carte cj : j.getDeckPlateau())
                            if (cj.getCouleur() == MARRON)
                                pieceBonus++;

                        for (Carte cj : mesJoueurs.get((ja.getIdJoueur() + 1) % mesJoueurs.size()).getDeckPlateau())
                            if (cj.getCouleur() == MARRON)
                                pieceBonus++;

                        for (Carte cj : mesJoueurs.get(ja.getIdJoueur() - 1 < 0 ? mesJoueurs.size() - 1 : ja.getIdJoueur() - 1).getDeckPlateau())
                            if (cj.getCouleur() == MARRON)
                                pieceBonus++;

                        j.recevoirPaiement(pieceBonus);
                        desc.append("1 pièce d'or par carte marron dans son deck et celui de ses voisins direct pour un total de +" + pieceBonus + "\n");
                        break;

                    case OR_CARTE_GRIS:
                        for (Carte cj : j.getDeckPlateau())
                            if (cj.getCouleur() == GRIS)
                                pieceBonus += 2;

                        for (Carte cj : mesJoueurs.get((ja.getIdJoueur() + 1) % mesJoueurs.size()).getDeckPlateau())
                            if (cj.getCouleur() == GRIS)
                                pieceBonus += 2;

                        for (Carte cj : mesJoueurs.get(ja.getIdJoueur() - 1 < 0 ? mesJoueurs.size() - 1 : ja.getIdJoueur() - 1).getDeckPlateau())
                            if (cj.getCouleur() == GRIS)
                                pieceBonus += 2;

                        j.recevoirPaiement(pieceBonus);
                        desc.append("2 pièces d'or par carte grise dans son deck et celui de ses voisins direct pour un total de +" + pieceBonus + "\n");
                        break;

                    case BONUS_ETAPE_MERVEILLE:
                        for (Etape e : j.getPlateau().getEtapes())
                            if (e.getEtat())
                                pieceBonus += 3;

                        j.recevoirPaiement(pieceBonus);
                        desc.append("3 pièces d'or par étapes construite de sa merveille pour un total de +" + pieceBonus + "\n");
                        break;

                    case BONUS_CARTE_MARRON:
                        for (Carte cj : j.getDeckPlateau())
                            if (cj.getCouleur() == MARRON)
                                pieceBonus++;

                        j.recevoirPaiement(pieceBonus);
                        desc.append("1 pièce d'or par carte marron dans son deck pour un total de +" + pieceBonus + "\n");
                        break;

                    case BONUS_CARTE_GRIS:
                        for (Carte cj : j.getDeckPlateau())
                            if (cj.getCouleur() == GRIS)
                                pieceBonus += 2;

                        j.recevoirPaiement(pieceBonus);
                        desc.append("2 pièce d'or par carte grise dans son deck pour un total de +" + pieceBonus + "\n");
                        break;

                    case BONUS_CARTE_JAUNE:
                        for (Carte cj : j.getDeckPlateau())
                            if (cj.getCouleur() == JAUNE)
                                pieceBonus++;

                        j.recevoirPaiement(pieceBonus);
                        desc.append("1 pièce d'or par carte jaune dans son deck pour un total de +" + pieceBonus + "\n");
                        break;

                    default:
                        // les autres cartes n'ont pas d'effet lorsqu'on la pose
                        break;
                    }
                }
            }
            break;

        case ConstruireMerveille:
            if (age >= 2) {
                if (j.getPlateau().getEtape(age - 1).getEtat() == true)
                    j.getPlateau().getEtape(age).construire();
            } else
                j.getPlateau().getEtape(age).construire();
            int etape = j.construireEtape(age, ja.getNumeroCarte());
            desc.append("Le joueur " + ja.getIdJoueur() + " a construit l'étape " + etape + " de sa merveille " + j.getPlateau().getNom());
            break;
        }
        return desc.toString();
    }

    public  Jeu(int nbJoueurs);

}