#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include "Employee_c.h"

  // To be used as "private data"
typedef struct {
  float Salary;
  int Years;
  char *FirstName;
  char *LastName;
}_EmployeeFields;

  // *************** Public gettors ***************
static const char *GetFirstName(Employee *emp)
{
  return ((_EmployeeFields *)(emp->data))->FirstName;
}

static const char *GetLastName(Employee *emp)
{
  return ((_EmployeeFields *)(emp->data))->LastName;
}

static float GetSalary(Employee *emp)
{
  return ((_EmployeeFields *)(emp->data))->Salary;
}

static int GetYears(Employee *emp)
{
  return ((_EmployeeFields *)(emp->data))->Years;
}

  // *************** Public settors ***************
static void SetFirstName(Employee *emp, const char *firstname)
{
  _EmployeeFields *ef = (_EmployeeFields *)emp->data;
  free(ef->FirstName);
  ef->FirstName = malloc(strlen(firstname) + 1);
  strcpy(ef->FirstName, firstname);
}

static void SetLastName(Employee *emp, const char *lastname)
{
  _EmployeeFields *ef = (_EmployeeFields *)emp->data;
  free(ef->LastName);
  ef->LastName = malloc(strlen(lastname) + 1);
  strcpy(ef->LastName, lastname);
}

static void SetSalary(Employee *emp, float salary)
{
  ((_EmployeeFields *)(emp->data))->Salary = salary;
}

static void SetYears(Employee *emp, int years)
{
  ((_EmployeeFields *)(emp->data))->Years = years;
}

  // *************** "Constructor" ***************
Employee *NewEmployee(const char *first, const char *last, float salary, int years)
{
    // Allocate space for the "object"
  Employee *emp = (Employee *)malloc(sizeof(Employee));

    // Allocate "private" data
  _EmployeeFields *ef = malloc(sizeof(_EmployeeFields));
  emp->data = ef;

    // Initialize "public methods"
  emp->Display = Display;
  emp->GetSalary = GetSalary;
  emp->GetYears = GetYears;
  emp->SetSalary = SetSalary;
  emp->SetYears = SetYears;
  emp->SetFirstName = SetFirstName;
  emp->SetLastName = SetLastName;
  emp->GetFirstName = GetFirstName;
  emp->GetLastName = GetLastName;

    // Initialize "private" data
  ef->FirstName = NULL;
  ef->LastName = NULL;
  emp->SetSalary(emp, salary);
  emp->SetYears(emp, years);
  emp->SetFirstName(emp, first);
  emp->SetLastName(emp, last);

    // Return "constructed" and initialized "object"
  return emp;
}

static void Display(Employee *this)
{
  printf("  Name: %s, %s\n", this->GetLastName(this), this->GetFirstName(this));
  printf("Salary: $%g\n", this->GetSalary(this));
  printf(" Years: %i\n", this->GetYears(this));
}

  // *************** "Destructor" ***************
void DeleteEmployee(Employee *emp)
{
  free(((_EmployeeFields *)emp->data)->FirstName);
  free(((_EmployeeFields *)emp->data)->LastName);
  free(emp->data);
  free(emp);
}