#include "campus.h"
#include "salaried.h"
#include "hourly.h"
#include "faculty.h"
#include "administrator.h"
#include "util.h"
#include <iostream>
#include <vector>
#include <cstdlib>
#include <fstream>

bool campus::contains(string name) {  //function used to verify if the string is already included
    employee * f = NULL;
    for(unsigned int i = 0; i < workers.size(); i++) {
        f = dynamic_cast<employee *>(workers[i]);
        if(f->get_name() == name) {
            return true;
        }
    }
    return false;
}

void campus::add_worker_from_parse(string name, string type, double pay_rate) { //add worker for parsed input
    bool passed = false;
    employee * h = NULL;
    int hours = 0;
    if(type == "H") {
        h = new hourly(name, pay_rate, hours, type);
        passed = true;
    }
    else if(type == "S") {
        h = new salaried(name, pay_rate, hours, type);
        passed = true;
    }
    else if(type == "F") {
        h = new faculty(name, pay_rate, hours, type);
        passed = true;
    }
    else if(type == "A") {
        h = new administrator(name, pay_rate, hours, type);
        passed = true;
    }
    if(passed == true) {
        workers.push_back(h);
    }
}

void campus::add_worker() {  //general add worker function which it gets the input
    employee * h = NULL;
    bool passed;
    string info;
    string name, type;
    int hours = 0;
    double pay_rate = 0;
    cout << "Enter info in following format" << endl;
    cout << "type pay_rate name" << endl;;
    getline(cin, info);
    passed = parse_n_load(info, name, type, pay_rate); 
    if(contains(name) == true) {
        cout << "already exists" << endl;
        return;
    }
    if(passed == false) {
        cout << "incorrect entry" << endl;
    }
    if(info[0] == ' ') {
        cout << "incorrect entry" << endl;
        passed = false;
    }
    else if(type == "H") {
        h = new hourly(name, pay_rate, hours, type);
    }
    else if(type == "S") {
        h = new salaried(name, pay_rate, hours, type);
    }
    else if(type == "F") {
        h = new faculty(name, pay_rate, hours, type);
    }
    else if(type == "A") {
        h = new administrator(name, pay_rate, hours, type);
    }
    if(passed == true) {
        workers.push_back(h);
    }
}
void campus::delete_worker() {
    string name;
    employee * h = NULL;
    cout << "Enter name of worker to delete" << endl;
    getline(cin, name);
    for(unsigned int i = 0; i < workers.size(); i++) {
        h = dynamic_cast<employee *>(workers[i]);
        if(h->get_name() == name) {
            delete h;
            workers.erase(workers.begin() + i);
        }
    }
}

void campus::display_worker() {  //allows for display of all employees or selected
    string input;
    employee * h = NULL;
    cout << "(a)ll workers or (o)ne worker?" << endl;
    cin >> input;
    cin.ignore();
    cout << "type // payrate // name // hours // salary" << endl;
    if(input == "a") {
        for(unsigned int i = 0; i < workers.size(); i++){
            h = dynamic_cast<employee *>(workers[i]);
            cout << *workers[i] << " $" << h->get_salary() << endl;
        }
    }
    if(input == "o") {
        cout << "name: ";
        employee * h = NULL;
        getline(cin, input);
        for(unsigned int i = 0; i < workers.size(); i++) {
            h = dynamic_cast<employee *>(workers[i]);
            if(h->get_name() == input) {
                cout << *h << " $" << h->get_salary() << endl;
            }
        }

    }
}

void campus::sort_name() {
    bool ready = true;
    employee * h = NULL;
    employee * j = NULL;
    while(ready) {
        for(unsigned int i = 0; i < workers.size() -1; i++) {
            h = dynamic_cast<employee *>(workers[i]);
            j = dynamic_cast<employee *>(workers[i+1]);
            ready = false;
            if(h->get_name() > j->get_name()) {
                workers.push_back(workers[i]);
                workers[i] = workers[i+1];
                workers[i+1] = workers[workers.size()-1];
                workers.pop_back();
                ready = true;
            }
        }
    }
}

void campus::sort_pay() {
    bool ready = true;
    employee * h = NULL;
    employee * j = NULL;
    while(ready) {
        for(unsigned int i = 0; i < workers.size() -1; i++) {
            h = dynamic_cast<employee *>(workers[i]);
            j = dynamic_cast<employee *>(workers[i+1]);
            ready = false;
            if(h->get_payrate() > j->get_payrate()) {
                workers.push_back(workers[i]);
                workers[i] = workers[i+1];
                workers[i+1] = workers[workers.size()-1];
                workers.pop_back();
                ready = true;
            }
        }
    }
}

void campus::sort_worker() {  //allows for either sort by name or by pay
    string input;
    cout << "sort by (n)ame or by (p)ay?" << endl;
    cin >> input;
    if(input == "n") {
        sort_name();
    }
    if(input == "p") {
        sort_pay();
    }
}

void campus::advance_month() {
    employee * h = NULL;
    for(unsigned int i = 0; i < workers.size(); i++) {
        h = dynamic_cast<employee *>(workers[i]);
        h->reset_hours();
    }
}

void campus::set_hours() {
    string name;
    employee * h = NULL;
    cout << "enter name of employee" << endl;
    getline(cin, name);
    for(unsigned int i = 0; i < workers.size(); i++) {
        h = dynamic_cast<employee *>(workers[i]);
        if(h->get_name() == name) {
            int input;
            cout << "enter hours" << endl;
            cin >> input;
            cin.ignore();
            h->set_hours(input);
        }
    }
}

void campus::add_files(campus c) { //function for i/o.  can either write to a file or take a file in
    string add_or_write;
    cout << "(a)dd or (w)rite to file?" << endl;
    cin >> add_or_write;
    cin.ignore();
    if(add_or_write == "a") {
        bool file_correct = false;
        string input, input_file_name;
        while(!file_correct) {
            cout << "please enter file name: ";
            getline(cin, input);
            ifstream inputs(input.c_str());
            if(inputs.good()) {
                input_file_name = input;
                file_correct = true;
                string lineread;
                while(getline(inputs, lineread)) {
                    bool worked;
                    string name, type;
                    double pay_rate;
                    worked = parse_n_load(lineread, name, type, pay_rate);
                    if(worked == true) {
                        add_worker_from_parse(name, type, pay_rate);
                    }
                    lineread = "";
                }
            }
            else {
                cerr << "incorrect file name" << endl;
            }
        }
    }
    if(add_or_write == "w") {
        bool file_correct = false;
        string input, input_file_name;
        string output_file_name;
        file_correct = false;
        while(!file_correct) {
            cout << "please enter file name: ";
            getline(cin, output_file_name);
            ofstream out(output_file_name.c_str());
            if(out.good()) {
                out << c;
                file_correct = true;
            }
            else {
                cerr << "incorrect file name" << endl;
            }
        }
    }
}

ostream & operator<<(ostream & os, campus & t) { //makes writing out to files much easier
    employee * h = NULL;
    for(unsigned int i = 0; i < t.workers.size(); i++) {
        h = dynamic_cast<employee *>(t.workers[i]);
        os << h->get_type() << " " << h->get_payrate() << " " << h->get_name() << "\n";
    }
    return os;
}
