//=============================================================================
// Gaertnerei-Personal-Verwaltung 5 (polymorph)
// 
// Nutzung von:
// * Vererbung fuer Angestellte & Vertriebler
// * Ein Container, der mit Zeigern arbeitet
//   - Aber keine dynamische Speicherverwaltung und Nutzung von Smart-Pointern, das in der Praxis notwendig waere
// * Nutzung von Ueberschreiben und Polymorphie

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

//-----------------------------------------------------------------------------
// Klasse aus der Vorlesung/Skript

class Datum
{
public:
   Datum();
   Datum(int, int, int);

   int getDay() const { return day_; }
   int getMonth() const { return month_; }

   friend ostream& operator<<(ostream&, const Datum&);

private:
   int day_;
   int month_;
   int year_;
};

Datum::Datum()
{
   time_t timer = time(0);
   tm* tblock = localtime(&timer);
   day_ = tblock->tm_mday;
   month_ = tblock->tm_mon+1;
   year_ = tblock->tm_year+1900;
}

Datum::Datum(int d, int m, int y)
   : day_(d), month_(m), year_(y)
{
}

ostream& operator<<(ostream& out, const Datum& d)
{
   char old = out.fill('0');
   out << setw(2) << d.day_ << '.' << setw(2) << d.month_ << '.' << setw(4) << d.year_;
   out.fill(old);
   return out;
}

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

class Mitarbeiter
{
public:
   Mitarbeiter(const string& n, const Datum& b, int s) : name_(n), birthday_(b), salary_(s) {}

   bool hasBirthdayAt(int day, int month) const { return birthday_.getDay() == day && birthday_.getMonth() == month; }

   virtual int calcSalary() const { return salary_; }

   virtual ostream& print(ostream& out) const
   {
      return out << name_ << ", geboren am " << birthday_ << ", Gehalt: " << calcSalary() << " Euro";
   }

private:
   string name_;
   Datum birthday_;
   int salary_;
};

ostream& operator<<(ostream& out, const Mitarbeiter& m)
{
   return m.print(out);
}

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

class Angestellter : public Mitarbeiter
{
public:
   using Mitarbeiter::Mitarbeiter;

   ostream& print(ostream& out) const override
   {
      out << "Angestellter: ";
      return Mitarbeiter::print(out);
   }
};

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

class Vertriebler : public Mitarbeiter
{
public:
   Vertriebler(const string& n, const Datum& b, int s, int u) : Mitarbeiter(n, b, s), umsatz_(u) {}

   int calcSalary() const override { return Mitarbeiter::calcSalary() + static_cast<int>(0.1 * umsatz_); }

   ostream& print(ostream& out) const override 
   {
      out << "Vertriebler:  ";
      return Mitarbeiter::print(out);
   }

private:
   int umsatz_;
};

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

int main()
{
   cout << "Gaertnerei 5 (polymorph)\n";

   Angestellter a1{ "Ada", { 1, 1,1970}, 600 };
   Angestellter a2{ "Eva", {17, 1,1980}, 500 };
   Angestellter a3{ "Max", {17, 4,1990}, 400 };
   Angestellter a4{ "Tom", {17, 1,2000}, 300 };

   Vertriebler v1{ "Lea", { 18, 1,1971}, 600, 2000 };
   Vertriebler v2{ "Tim", { 17, 1,1982}, 500, 4000 };

   vector<Mitarbeiter*> db{ &a1, &a2, &v1, &a3, &v2, &a4 };

   for (string cmd;;)
   {
      cout << "\n\nKommando: ";
      getline(cin, cmd);
      cout << '\n';

      if (cmd == "end")
      {
         break;
      }

      if (cmd == "geburtstag")
      {
         cout << "Heutige Geburtstage:\n";
         const Datum today;
         const int day = today.getDay();
         const int month = today.getMonth();
         for (const Mitarbeiter* pm : db)
         {
            if (pm->hasBirthdayAt(day, month))
            {
               cout << "- " << *pm << '\n';
            }
         }
         continue;
      }

      if (cmd == "geld")
      {
         cout << "Schecks drucken:\n";
         for (const Mitarbeiter* pm : db)
         {
            cout << "- " << *pm << '\n';
         }
         continue;
      }

      cout << "Unbekanntes Kommando\n";
   }

   cout << "Tschau\n\n";
}
