#include <iostream.h>
#include <new.h>
#include <typeinfo.h>
#include "impl.h"
#include "user.h"

employeeList* employeeList::first = 0;
employeeList* employeeList::last = 0;

employeeList::~employeeList() 
{
  delete Empl;  
}

void employeeList::addEmployee(employee* e)
{
  if (first == 0) 
  {
    first = last = new employeeList;
  }
  else 
  {
    last->Next = new employeeList;
    last = last->Next;
  }
  last->Empl = e;
}

company::company() 
{
  EmployeeList = new employeeList;
}

company::~company()
{
  employeeList* el = EmployeeList;
  employeeList* next = (el != 0) ? el->next() : 0; 
  while (el != 0) 
  {
    delete el->empl();
    delete el;
    el = next;
    next = (el != 0) ? el->next() : 0;
  }
}

void company::addManager(char* name, int hourRate, int experience)
{
  manager* m = new manager(name, hourRate, experience);
  EmployeeList->addEmployee(m); 
}

//
// Because the member functions are not virtual, the user is 
// obliged to ensure that the added member functions 
// (setOvertimeRate, addOvertime, resetOvertime and overtimePay)
// are used only if the employee referred to is a programmer.
// A dynamic_cast or a typeid can be used to ensure the employee
// referred to is a programmer.
//

void company::addProgrammer(char* name, int hourRate, int ovRate)
{
  programmer* p = new programmer(name, hourRate);
  p->setOvertimeRate(ovRate);
  EmployeeList->addEmployee(p);
}

void company::addOvertime(char* name, int overtime)
{
  for (employeeList* el = EmployeeList->first;
       el != 0;
       el = el->next()) 
  {
    if (!strcmp(name, el->empl()->name())) 
    {
      programmer* pe = dynamic_cast<programmer*>(el->empl());
      if (pe != 0) 
        pe->addOvertime(overtime);

      return;
    }
  }  
}

void company::payRoll()
{
  int expense = 0;
  
  for (employeeList* el = EmployeeList->first; 
       el != 0;
       el = el->next())
  {
    int pay = el->empl()->salary();
    programmer* pe = dynamic_cast<programmer*>(el->empl());
    if (pe != 0)
    {
      pay += pe->overtimePay();
      pe->resetOvertime();
    }
    cout << el->empl()->name() << " is a " << typeid(*(el->empl())).name()
         << " who was paid $" << pay << " this week." << endl;
    expense += pay;
  }
  cout << "The total expense in salary this week is " << expense << "." << endl;
}

