//********************************************************
//
// Assignment 11 - Object Oriented Design
//
// Name: John Semenuk
//
// Class: C Programming, Spring 2026
//
// Date: April 25, 2026
//
// Description: An object oriented program design using
// C++ that will process our existing set of employees.
// It utilizes a class called Employee and generates an
// array of objects that are used to store, calculate,
// and print out a simple report of inputted and calculated
// values.
//
//
// Object Oriented Design (using C++)
//
//********************************************************

#include <iomanip>    // std::setprecision, std::setw
#include <iostream>   // std::cout, std::fixed
#include <string>     // string functions
#include <cctype>

using namespace std;

// define constants
#define STD_HOURS 40.0
#define OT_RATE 1.5
#define MA_TAX_RATE 0.05
#define NH_TAX_RATE 0.0
#define VT_TAX_RATE 0.06
#define CA_TAX_RATE 0.07
#define DEFAULT_TAX_RATE 0.08
#define NAME_SIZE 20
#define TAX_STATE_SIZE 3
#define FED_TAX_RATE 0.25
#define FIRST_NAME_SIZE 10
#define LAST_NAME_SIZE 10
 
#define EMP_SIZE 5

using std::string;

// class Employee
class Employee
{
private:
    
    // private data available only to member functions
	// all data is initialized to support creating instances that
	// are not done via a full constructor with data to be used
    
   	string firstName = "";     // Employee First Name
	string lastName  = "";     // Employee Last Name
	string taxState = "";      // Employee Tax State
	int clockNumber = 0;       // Employee Clock Number
	float wageRate = 0.0;      // Hourly Wage Rate
	float hours = 0.0;         // Hours worked in a week
	float overTimeHrs = 0.0;   // Overtime Hours worked
	float grossPay = 0.0;      // Weekly Gross Pay
	float stateTax = 0.0;      // State Tax
	float fedTax = 0.0;        // Fed Tax
	float netPay = 0.0;        // Net Pay

  	// private functions for call only by an Employee object
	// ... these are gernally more complex computations
    float calcOverTimeHrs();
    float calcGrossPay();
    float calcStateTax();
    float calcFedTax();
    float calcNetPay();

   	// Delcare "getter" function prototypes to retrieve private data
	// Note: The inline keyword is not required for the prototypes
    string getFirstName();
    string getLastName();
    string getTaxState();
    int getClockNumber();
    float getWageRate();
    float getHours();
    float getOverTimeHrs();
    float getGrossPay();
    float getStateTax();
    float getFedTax();
    float getNetPay();

public:
    
    // public member functions that can be called
	// to access private data member items
 
	// public no argument constructor with defaults
	// All Employee class data will be initialized to defaults
    
    Employee() {}    // destructor

    Employee(string f, string l, string s,
             int c, float w, float h);

    ~Employee() {}
    // print out Employee data to the console
    void printEmployee();
};// End class declarations.

// ================= GETTERS =================
inline string Employee::getFirstName() { return firstName; }
inline string Employee::getLastName() { return lastName; }
inline string Employee::getTaxState() { return taxState; }
inline int Employee::getClockNumber() { return clockNumber; }
inline float Employee::getWageRate() { return wageRate; }
inline float Employee::getHours() { return hours; }
inline float Employee::getOverTimeHrs() { return overTimeHrs; }
inline float Employee::getGrossPay() { return grossPay; }
inline float Employee::getStateTax() { return stateTax; }
inline float Employee::getFedTax() { return fedTax; }
inline float Employee::getNetPay() { return netPay; }

// private member function to calculate Overtime Hours
float Employee::calcOverTimeHrs()
{
    // Calculate the overtime hours for the week
    overTimeHrs = (hours > STD_HOURS) ? (hours - STD_HOURS) : 0;
    return overTimeHrs;
}// the calculated overtime hours

float Employee::calcGrossPay()
{
    if (overTimeHrs > 0)
        grossPay = (STD_HOURS * wageRate) + (overTimeHrs * wageRate * OT_RATE);
    else
        grossPay = hours * wageRate;

    return grossPay;
}

float Employee::calcStateTax()
{
    float rate;

    if (taxState == "MA") rate = MA_TAX_RATE;
    else if (taxState == "VT") rate = VT_TAX_RATE;
    else if (taxState == "NH") rate = NH_TAX_RATE;
    else if (taxState == "CA") rate = CA_TAX_RATE;
    else rate = DEFAULT_TAX_RATE;

    stateTax = grossPay * rate;
    return stateTax;
}

float Employee::calcFedTax()
{
    fedTax = grossPay * FED_TAX_RATE;
    return fedTax;
}

float Employee::calcNetPay()
{
    netPay = grossPay - stateTax - fedTax;
    return netPay;
}

// constructor with arguments
Employee::Employee(string f, string l, string s,
                   int c, float w, float h)
{
    firstName = f;
    lastName = l;

    if (islower(s[0])) s[0] = toupper(s[0]);
    if (islower(s[1])) s[1] = toupper(s[1]);
    taxState = s;

    clockNumber = c;
    wageRate = w;
    hours = h;

    overTimeHrs = calcOverTimeHrs();
    grossPay = calcGrossPay();
    stateTax = calcStateTax();
    fedTax = calcFedTax();
    netPay = calcNetPay();
}

// a member function to print out the info in a given Employee object
void Employee::printEmployee()
{
    cout << "\n\n*** Entered Details are ***\n";
    cout << "First Name: " << getFirstName() << endl;
    cout << "Last Name: " << getLastName() << endl;
    cout << "Tax State: " << getTaxState() << endl;
    cout << "Clock Number: " << getClockNumber() << endl;
    cout << "Wage Rate: " << getWageRate() << endl;
    cout << "Hours: " << getHours() << endl;

    cout << "\n*** Calculated Values are ***\n";
    cout << "Overtime Hours : " << getOverTimeHrs() << endl;
    cout << "Gross Pay : $" << getGrossPay() << endl;
    cout << "State Tax : $" << getStateTax() << endl;
    cout << "Federal Tax : $" << getFedTax() << endl;
    cout << "Net Pay : $" << getNetPay() << endl;
}

// main function to start the processing
int main()
{
    cout << fixed << setprecision(2);
 
    Employee e[EMP_SIZE];
 
    for (int i = 0; i < EMP_SIZE; i++)
    {
        string f, l, s;
        int c;
        float w, h;
 
        cout << "\n\n Enter Employee First Name: " << endl;
        cin >> f;
 
        cout << " Enter Employee Last Name: " << endl;
        cin >> l;
 
        cout << " Enter Employee Tax State: " << endl;
        cin >> s;
 
        cout << " Enter Employee Clock Number: " << endl;
        cin >> c;
 
        cout << " Enter Employee Hourly Wage Rate: " << endl;
        cin >> w;
 
        cout << " Enter Employee Hours Worked for the Week: " << endl;
        cin >> h;
 
        e[i] = Employee(f, l, s, c, w, h);
        e[i].printEmployee();
    }
 
    return 0;
}