//=============================================================================

#include <iostream>
#include <limits>
#include <map>
#include <string>
using namespace std;

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

using book_type = map<string, string>;

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

bool starts_with(const string& src, const string& pattern)
{
   if (src.length() < pattern.length())
   {
      return false;
   }
   return src.substr(0, pattern.length()) == pattern;
}

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

void list_entries(const book_type& book)
{
   cout << book.size() << " Eintraege:\n";
   for (auto& [name, no] : book)
   {
      cout << "* " << name << " => " << no << '\n';
   }
}

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

void search_entries(const book_type& book)
{
   string s;
   cout << "Suchen nach: ";
   getline(cin, s);

   auto lower = book.lower_bound(s);
   if (lower == cend(book) || !starts_with(lower->first, s))
   {
      cout << "\nKein Name im Telefonbuch beginnt mit \"" << s << "\".\n";
      return;
   }

   cout << "\nGefunden:\n";
   auto eit = cend(book);
   for (; lower != eit; ++lower)
   {
      if (!starts_with(lower->first, s)) break;
      cout << "* " << lower->first << " => " << lower->second << '\n';
   }
}

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

void new_entry(book_type& book)
{
   cout << "Neuer Eintrag\n";

   string name;
   cout << "> Name: ";
   getline(cin, name);

   if (name.empty())
   {
      cout << "Abbruch 'neuer Eintrag', wegen leeren Namens\n";
      return;
   }
   if (book.count(name) > 0)
   {
      cout << "Abbruch 'neuer Eintrag', da Name schon vorhanden\n";
      return;
   }

   string no;
   cout << "> Nr.: ";
   getline(cin, no);

   if (no.empty())
   {
      cout << "Abbruch 'neuer Eintrag, wegen leerer Nummer'\n";
      return;
   }

   book.insert({name, no});
}

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

int main()
{
   cout << "Aufg_12_09_Telefonbuch_2\n\n";

   book_type book 
   {
      { "Detlef", "0123 / 12 21 1" },
      { "Edgar", "0111 / 11 11 1" },
      { "Edmund", "0222 / 33 22 11" },
      { "Dietmar", "0321 / 888 222 99" },
      { "Karl", "0111 / 11 22 33" },
      { "Erwin", "0222 / 33 22 33" },
      { "Bernd", "0555 / 55 55 55" }
   };

   for (char c;;)
   {
      cout << "\nBitte waehlen Sie eine Aktion: \n"
         << "- e : Programmende\n"
         << "- l : Alle Eintraege auflisten\n"
         << "- s : Nach Eintrag suchen\n"
         << "- n : Neuen Eintrag eingeben\n"
         << "> ";
      cin >> c;
      cin.ignore(numeric_limits<streamsize>::max(), '\n');
      cout << '\n';

      switch (c)
      {
      case 'e':
         cout << "Auf Wiedersehen\n";
         return 0;
      case 'l':
         list_entries(book);
         break;
      case 's':
         search_entries(book);
         break;
      case 'n':
         new_entry(book);
         break;
      }
   }
}
