/********************************************************
//
// Assignment 11 - Object Oriented Design
//
// Name: <replace with your name>
//
// Class: C Programming, <replace with Semester and Year>
//
// Date: <replace with the current date>
//
// Description: An object-oriented program design using
// C++ that processes a 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

// define constants
#define EMP_SIZE 5
#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

using namespace std;

// class Employee
class Employee {
private:
    string firstName;     // Employee First Name
    string lastName;      // Employee Last Name
    string taxState;      // Employee Tax State
    int clockNumber;      // Employee Clock Number
    float wageRate;       // Hourly Wage Rate
    float hours;          // Hours worked in a week
    float overTimeHrs;    // Overtime Hours worked
    float grossPay;       // Weekly Gross Pay
    float stateTax;       // State Tax
    float fedTax;         // Fed Tax
    float netPay;         // Net Pay

    float calcOverTimeHrs() {
        return (hours > STD_HOURS) ? (hours - STD_HOURS) : 0;
    }

    float calcGrossPay() {
        return (overTimeHrs > 0) ? 
            (STD_HOURS * wageRate + overTimeHrs * (wageRate * OT_RATE)) : 
            (wageRate * hours);
    }

    float calcStateTax() {
        if (taxState == "MA") return grossPay * MA_TAX_RATE;
        if (taxState == "VT") return grossPay * VT_TAX_RATE;
        if (taxState == "NH") return grossPay * NH_TAX_RATE;
        if (taxState == "CA") return grossPay * CA_TAX_RATE;
        return grossPay * DEFAULT_TAX_RATE;
    }

    float calcFedTax() {
        return grossPay * FED_TAX_RATE;
    }

    float calcNetPay() {
        return grossPay - (stateTax + fedTax);
    }

public:
    Employee() : firstName(""), lastName(""), taxState(""), clockNumber(0), wageRate(0), hours(0), 
                 overTimeHrs(0), grossPay(0), stateTax(0), fedTax(0), netPay(0) {}

    Employee(string myFirstName, string myLastName, string myTaxState, 
             int myClockNumber, float myWageRate, float myHours)
    : firstName(myFirstName), lastName(myLastName), clockNumber(myClockNumber), 
      wageRate(myWageRate), hours(myHours) {
        // Normalize taxState to uppercase
        for (auto &c : myTaxState) c = toupper(c);
        taxState = myTaxState;

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

    ~Employee() {}

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

    void printEmployee() {
        cout << "\n\n *** Entered Details are *** \n";
        cout << "\n First Name: " << getFirstName();
        cout << "\n Last Name: " << getLastName();
        cout << "\n Tax State: " << getTaxState();
        cout << "\n Clock Number: " << getClockNumber();
        cout << "\n Wage Rate: $" << getWageRate();
        cout << "\n Hours Worked: " << getHours();
        
        cout << "\n\n *** Calculated Values are *** \n";
        cout << "\n Overtime Hours: " << getOverTimeHrs();
        cout << "\n Gross Pay: $" << getGrossPay();
        cout << "\n State Tax: $" << getStateTax();
        cout << "\n Federal Tax: $" << getFedTax();
        cout << "\n Net Pay: $" << getNetPay();
        cout << "\n";
    }
};

int main() {
    string myFirstName, myLastName, myTaxState;
    int myClockNumber;
    float myWageRate, myHours;

    cout << fixed << setprecision(2);

    Employee e[EMP_SIZE];

    for (int i = 0; i < EMP_SIZE; ++i) {
        cout << "\n\n Enter Employee First Name: ";
        cin >> myFirstName;
        cout << "\n Enter Employee Last Name: ";
        cin >> myLastName;
        cout << "\n Enter Employee Tax State: ";
        cin >> myTaxState;
        cout << "\n Enter Employee Clock Number: ";
        cin >> myClockNumber;
        cout << "\n Enter Employee Hourly Wage Rate: ";
        cin >> myWageRate;
        cout << "\n Enter Employee Hours Worked for the Week: ";
        cin >> myHours;

        e[i] = Employee(myFirstName, myLastName, myTaxState, myClockNumber, myWageRate, myHours);

        e[i].printEmployee();
    }

    return 0;
}
