#include <iostream>
#include <vector>
#include <string>
using namespace std;

/* 
 CONSTAT : c'est encore mieux (on a amélioré le français), mais :
   3) Généricité : on ne peut faire que de la fondue ; pourquoi pas autre chose ? facile ?

mineurs/plus tard:
   4) rendre la saisie plus robuste : do-while
*/

// ==== Type de données =============================

struct Mot {
  string mot;
  string pluriel; // "" pour les invariables, suffixe sur 1 char ou mot entier sinon
  bool feminin; // ou masculin (false)
};

typedef double Quantite;

struct Ingredient
{
  string nom;
  Quantite qtt;
  Mot unite;
};

struct Recette {
  Mot nom;
  unsigned int nb_personnes;
  vector<Ingredient> ingredients; // liste et quantités
};

// ==== Fonctions ===================================

unsigned int demander_nb_convives()
{
  /* On supposera pour cet exercice que l'utilisateur ne saisit que
   * des valeurs strictement positives mais nous pourrions faire mieux.
   */
  cout << "Entrez le nombre de personnes invitées : ";
  unsigned int nb_convives(0);
  cin >> nb_convives;
  return nb_convives;
}

// --------------------------------------------------

// version 2 : ne modifie pas la recette ; voir 2a.cc pour la version 1
Recette adapter(Recette const& r, unsigned int nb_convives) 
{
  Recette retour(r);
  
  // Mise à jour des quantités en fonction du nombre de convives :

  double ratio(nb_convives); // Notez le 'double' ici...
  ratio /= r.nb_personnes;   // ... pour éviter une division entière.

  for (auto& ingredient : retour.ingredients) { // ATTENTION ! n'oubliez pas le & ici !
    ingredient.qtt *= ratio;
  }

  retour.nb_personnes = nb_convives;

  return retour;
}

// --------------------------------------------------

bool est_voyelle(char c) {
  return "aeiouyAEIOUY"s.find(c) != string::npos;
  // pour les caractères accentués, c'est franchement plus compliqué (encodage)
}

// --------------------------------------------------

// Pensez à MODULARISER : faire aussi un affiche() pour Mot !!

void afficher(Mot const& m, bool pluriel = false)
{
  if (pluriel and not m.pluriel.empty()) {
    if (m.pluriel.size() == 1) {
      cout << m.mot << m.pluriel;
    } else {
      cout << m.pluriel;
    }
  } else {
    // singulier
    cout << m.mot;
  }
}

void afficher(Ingredient const & ing)
{
  cout << ing.qtt << ' ';
  afficher(ing.unite, ing.qtt > 1.0);
  if (est_voyelle(ing.nom.front())) {
    cout << " d'";
  } else {
    cout << " de ";
  }
  cout << ing.nom;
}

void afficher(Recette const & rec)
{
  cout << "Pour faire un";
  if (rec.nom.feminin) cout << 'e';
  cout << " " << rec.nom.mot << " pour " << rec.nb_personnes << " personne";
  if (rec.nb_personnes > 1) cout << 's';
  cout << "," << endl;
  cout << "il vous faut : " << endl;
  for (auto const& ingredient : rec.ingredients) {
    cout << " - ";
    afficher(ingredient);
    cout << endl;
  }
}

// ==== Main ========================================

int main()
{
  // Quelques unités utiles
  const Mot gramme   ({ "gr"    , "" , false });
  const Mot decilitre({ "dl"    , "" , false });
  const Mot gousse   ({ "gousse", "s", true  });

  // La recette :
  Recette fondue(
     { .nom = { "fondue fribourgeoise", "fondues fribourgeoises", true },
       .nb_personnes = 4,     // nombre de personnes pour la recette de base
                   
       // Pour faire une fondue fribourgeoise pour 4 personnes il faut : 
       .ingredients = {
         { "Vacherin fribourgeois", 800.0, gramme },
         { "eau"                  ,   2.0, decilitre },
         { "ail"                  ,   2.0, gousse },
         { "pain"                 , 400.0, gramme }
       }
   });

  afficher(adapter(fondue, demander_nb_convives()));
 
  return 0;
}

