//********************************************************
//
// Assignment 11 - Object Oriented Design
//
// Name: John Semenuk
// Class: C Programming, Spring 2026
// Date: April 27, 2026
//
//********************************************************

#include <iostream>
#include <iomanip>
#include <string>
#include <cctype>

using namespace std;

#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 FED_TAX_RATE 0.25
#define EMP_SIZE 5


class Employee
{
private:
    string firstName;
    string lastName;
    string taxState;
    int clockNumber;
    float wageRate;
    float hours;

    float overTimeHrs;
    float grossPay;
    float stateTax;
    float fedTax;
    float netPay;

    float calcOverTimeHrs();
    float calcGrossPay();
    float calcStateTax();
    float calcFedTax();
    float calcNetPay();

    string getFirstName();
    string getLastName();
    string getTaxState();
    int getClockNumber();
    float getWageRate();
    float getHours();
    float getOverTimeHrs();
    float getGrossPay();
    float getStateTax();
    float getFedTax();
    float getNetPay();

public:
    Employee() {}

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

    ~Employee() {}

    void printEmployee();
};

// ================= 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; }

// ================= CALCULATIONS =================
float Employee::calcOverTimeHrs()
{
    overTimeHrs = (hours > STD_HOURS) ? hours - STD_HOURS : 0;
    return overTimeHrs;
}

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 =================
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();
}

// ================= PRINT =================
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 =================
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;
}