//********************************************************
//
// Assignment 11 - Object Oriented Design
//
// Name: <Matthew Tracy>
//
// Class: C Programming, <Spring 2026>
//
// Date: <04/25/26>
//
// 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 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();

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

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

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

// TODO - Add an inline "getter" function that will retrieve the employee stateTax
inline float Employee::getstateTax() {
	return stateTax;
}
// TODO - Add an inline "getter" function that will retrieve the employee fedTax
inline float Employee::getfedTax() {
	return fedTax;
}
// TODO - 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

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

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

	// TODO - 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();

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

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

	// TODO - 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