//********************************************************
//
//  main.cpp
//  project 11
//
//  Created by Austin Taylor on 4/25/26.
//
// C programing spring 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

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 generally more complex computations.
    float  calcOverTimeHrs();
    float  calcGrossPay();
    float  calcStateTax();
    float  calcFedTax();
    float  calcNetPay();

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

    // done - Declare a "getter" function declaration that will retrieve the employee stateTax
    float getstateTax();

    // done - Declare a "getter" function declaration that will retrieve the employee fedTax
    float getfedTax();

    // done - Declare a "getter" function declaration that will retrieve the employee netPay
    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() {}

    // public constructor with arguments passed to it
    Employee (string myFirstName, string myLastName, string myTaxState,
              int myClockNumber, float myWageRate, float myHours);

    ~Employee();  // destructor

    // print out Employee data to the console
    void   printEmployee();


};  // End class declarations.

// The inlined Employee members follow...

// A "getter" function that will retrieve the First Name
inline string Employee::getFirstName() {
    return firstName;
}

// A "getter" function that will retrieve the employee Last Name
inline string Employee::getLastName() {
    return lastName;
}

// A "getter" function that will retrieve the employee Tax State
inline string Employee::getTaxState() {
    return taxState;
}

// A "getter" function that will retrieve the employee Clock Number
inline int Employee::getClockNumber() {
    return clockNumber;
}

// A "getter" function that will retrieve the employee Wage Rate
inline float Employee::getWageRate() {
    return wageRate;
}

// A "getter" function that will retrieve the employee Hours Worked
inline float Employee::getHours() {
    return hours;
}

// A "getter" function that will retrieve the employee Overtime Hours
inline float Employee::getOverTimeHrs() {
    return overTimeHrs;
}

// A "getter" function that will retrieve the employee Gross Pay
inline float Employee::getGrossPay() {
    return grossPay;
}

// done - Add an inline "getter" function that will retrieve the employee stateTax
inline float Employee::getstateTax(){
    return stateTax;
}

// done - Add an inline "getter" function that will retrieve the employee fedTax
inline float Employee::getfedTax(){
    return fedTax;
}

// done - Add an inline "getter" function that will retrieve the employee netPay
inline float Employee::getnetPay(){
    return netPay;
}


// private member function to calculate Overtime Hours
float Employee::calcOverTimeHrs ( )
{
    // Calculate the overtime hours for the week
    if (hours > STD_HOURS)
        overTimeHrs = hours - STD_HOURS;  // ot hours
    else
        overTimeHrs = 0;  // no ot hours

    // the calculated overtime hours
    return (overTimeHrs);

} // calcOverTimeHrs

// private member function to calculate Gross Pay
float Employee::calcGrossPay ( )
{
    // Process gross pay based on if there is overtime
    if (overTimeHrs > 0)
    {
        // overtime
        grossPay = (STD_HOURS * wageRate) // normal pay
                   + (overTimeHrs * (wageRate * OT_RATE)); // ot pay
    }
    else  // no overtime pay
    {
        grossPay = wageRate * hours;  // normal pay
    }

    // the calculated gross pay
    return (grossPay);

} // calcGrossPay

// private member function to calculate State Tax
float Employee::calcStateTax ()
{

    float theStateTax; // calculated state tax

    theStateTax = grossPay;  // initialize to gross pay

    // calculate state tax based on where employee resides

    if (taxState.compare("MA") == 0)
        theStateTax *= MA_TAX_RATE;
    else if (taxState.compare("VT") == 0)
        theStateTax *= VT_TAX_RATE;
    else if (taxState.compare("NH") == 0)
        theStateTax *= NH_TAX_RATE;
    else if (taxState.compare("CA") == 0)
        theStateTax *= CA_TAX_RATE;
    else
        theStateTax *= DEFAULT_TAX_RATE;  // any other state

    // return the calculated state tax
    return (theStateTax);

} // calcStateTax

// private member function to calculate Federal Tax
float Employee::calcFedTax ()
{

    float theFedTax; // The calculated Federal Tax

    // Federal Tax is the same for all regardless of state
    theFedTax = grossPay * FED_TAX_RATE;

    // return the calculated federal tax
    return (theFedTax);

} // calcFedTax

// private member function to calculate Net Pay
float Employee::calcNetPay ()
{

    float theNetPay;      // total take home pay (minus taxes)
    float theTotalTaxes;  // total taxes owed

    // calculate the total taxes owed
    theTotalTaxes = stateTax + fedTax;

    // calculate the net pay
    theNetPay = grossPay - theTotalTaxes;

    // return the calculated net pay
    return (theNetPay);

} // calcNetPay


// constructor with arguments
Employee::Employee (string myFirstName, string myLastName, string myTaxState,
                    int myClockNumber, float myWageRate, float myHours)
{
    // initialize all member data items
    firstName = myFirstName;            // input
    lastName = myLastName;             // input

    // Convert myTaxState to uppercase if entered in lowercase
    if (std::islower(myTaxState[0]))
        myTaxState[0] = std::toupper(myTaxState[0]);
    if (std::islower(myTaxState[1]))
        myTaxState[1] = std::toupper(myTaxState[1]);

    taxState = myTaxState;                             // input
    clockNumber = myClockNumber;           // input
    wageRate = myWageRate;                       // input
    hours = myHours;                                     // input
    overTimeHrs = calcOverTimeHrs();         // calculated overtime hours
    grossPay = calcGrossPay();                      // calculated gross pay

    // done - set stateTax as the return from calcStateTax member function
    stateTax = calcStateTax();

    // done - set fedTax as the return from calcFedTax member function
    fedTax = calcFedTax();

    // done - set netPay as the return from calcNetPay member function
    netPay = calcNetPay();

} // Employee constructor

// a member function to print out the info in a given Employee object
void Employee::printEmployee() {

    // Display the entered input on the Employee
    cout << endl << endl <<"*** Entered Details are *** " << endl;
    cout << endl <<" First Name: "<< getFirstName();
    cout << endl <<" Last Name: "<<  getLastName();
    cout << endl <<" Tax State: "<<  getTaxState();
    cout << endl <<" Clock Number: "<< getClockNumber();
    cout << endl <<" Wage Rate: "<< getWageRate ();
    cout << endl <<" Hours: "<< getHours ();

    // Display the calculated values of the Employee
    cout<< endl << endl <<" *** Calculated Values are *** " << endl;

    // print out overtime hours based on the employee information entered
    cout << endl << " Overtime Hours : " <<  getOverTimeHrs();

    // print out gross pay based on the employee information entered
    cout << endl << " Gross Pay : $ " <<  getGrossPay();

    // done - Add cout statement with call to stateTax getter function
    cout << endl << " State Tax : $ " << getstateTax();

    // done - Add cout statement with call to fedTax getter function
    cout << endl << " Fed Tax : $ " << getfedTax();

    // done - Add cout statement with call to netPay getter function
    cout << endl << " Net Pay : $ " << getnetPay();

    // add a new line to separate the next employee
    cout <<"\n";

} // printEmployee

// Employee's destructor
Employee::~Employee()
{
    // nothing to print here, but could ...
}


// main function to start the processing
int main ()
{
    // local variables to collect user input

    string myFirstName;          // First Name to input
    string myLastName;          // Last Name to input
    string myTaxState;            // Tax State to input
    int myClockNumber;        // Clock Number to input
    float myWageRate;          // Wage Rate to input
    float myHours;                 // Hours to input

    cout << fixed                   // fix the number of decimal digits
         << setprecision(2);     // to 2

    // Array of Objects to store each of our employees
    // This calls the default constructor for each array element
    Employee e[EMP_SIZE];

    // prompt for information to read in employee information
    for (int i = 0; i < EMP_SIZE; ++i)
    {
        // Enter Employee Information
        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;

        // Call our constructor to create an employee object
        // using the input entered above.  The constructor
        // will also put into motion the execution of the
        // various private member functions which will
        // calculate the overtime, gross pay, state tax, federal
        // tax, and net pay for the current employee.

        // The updated object will be returned and placed in the
        // the element of our array of objects named "e", using the index
        // of the current value of our loop index "i" ... thus: e[i]
        e[i] = {myFirstName, myLastName, myTaxState,
                   myClockNumber, myWageRate, myHours
                 };

        // Call the printEmployee public member function to display all
        // the inputted and calculated values for the current employee
        e[i].printEmployee();

    } // for

    return 0;

} // main
