#include <iostream>
using namespace std;

int sizeofList = 3;
struct Tutor
{
    int id;             // Tutor id
    string fname;       // Tutor first name
    string lname;       // Tutor last name
    string datej;       // Date joined
    string datet;       // Date terminated
    int hourlyrate;     // Hourly pay rate
    string phone;       // Phone number
    string address;     // Address
    int tuitioncode;    // Tuition centre code
    string tuitionname; // Tuition centre name
    int subjectcode;    // Subject code
    string subjectname; // Subject name
    double rating;      // Performance rating
    Tutor *next;        // next node address
} * head;

int countNode()
{
    Tutor *current = head;
    int count = 0;

    while (current != NULL)
    {
        count++;
        current = current->next;
    }
    return count;
}

Tutor *createNewNode(int id, string fname, string lname, string datej, string datet, int hourlyrate, string phone,
                     string address, int tuitioncode, string tuitionname, int subjectcode, string subjectname, double rating) // create new node
{
    Tutor *newnode = new Tutor;
    newnode->id = id;
    newnode->fname = fname;
    newnode->lname = lname;
    newnode->datej = datej;
    newnode->datet = datet;
    newnode->hourlyrate = hourlyrate;
    newnode->phone = phone;
    newnode->address = address;
    newnode->tuitioncode = tuitioncode;
    newnode->tuitionname = tuitionname;
    newnode->subjectcode = subjectcode;
    newnode->subjectname = subjectname;
    newnode->rating = rating;
    newnode->next = NULL;
    return newnode;
}
void insert(Tutor *newnode) // add new tutor record
{
    if (head == NULL)
    {
        head = newnode;
    }
    else
    {
        Tutor *current = head;
        while (current->next != NULL)
        {
            current = current->next;
        }
        current->next = newnode;
    }
    ::sizeofList++;
}

void add()
{
    int id, tuitioncode, subjectcode, hourlyrate, choice = 1;
    string fname, lname, datej, datet, phone, address, tuitionname, subjectname;
    double rating;
    while (choice == 1)
    {
        cout << "Enter id :";
        cin >> id;

        cout << "Enter first name :";
        cin >> fname;

        cout << "Enter last name :";
        cin >> lname;

        cout << "Enter date joined :";
        cin >> datej;

        cout << "Enter date terminated :";
        cin >> datet;

        cout << "Enter hourly pay rate :";
        cin >> hourlyrate;

        cout << "Enter phone number :";
        cin >> phone;

        cout << "Enter address :";
        cin >> address;

        cout << "Enter Tuition code :";
        cin >> tuitioncode;

        cout << "Enter tuition name :";
        cin >> tuitionname;

        cout << "Enter subject code :";
        cin >> subjectcode;

        cout << "Enter subject name :";
        cin >> subjectname;

        cout << "Enter performance rating :";
        cin >> rating;

        Tutor *newnode = createNewNode(id, fname, lname, datej, datet, hourlyrate, phone, address, tuitioncode, tuitionname, subjectcode, subjectname, rating);
        insert(newnode);

        cout << "Do you still want to add a new tutor?"
             << "1 : Yes, others : No";
        cin >> choice;
    }
}

void remove(int keyword) // delete a tutor record based on specific keyword
{
    // scenario 1 : lsit is still empty
    if (head == NULL)
    {
        cout << "Empty list ! Nothing to delete!" << endl;
        return;
    }
    // scenario 2 : head car name= keyword
    else if (head->id == keyword) // delete from the front of the list
    {
        Tutor *current = head;
        head = head->next;
        cout << "Tutor with " << head->id << " is deleted from the list!" << endl;
        delete current;
        ::sizeofList--;
        return;
    }
    // scenario 3 : where the keyword unable to find in first item
    else
    {
        Tutor *current = head->next;
        Tutor *previous = head; // standby during deletion.

        while (current != NULL)
        {
            if (current->id == keyword)
            {
                previous->next = current->next;
                cout << "Tutor with" << current->id << " is deleted from the list!" << endl;
                delete current;
                ::sizeofList--;
                return;
            }
            previous = current;
            current = current->next;
        }
        cout << "Tutor with " << keyword << "is not  found in the list!" << endl;
    }
}

Tutor *swap(Tutor *ptr1, Tutor *ptr2)
{
    Tutor *tmp = ptr2->next;
    ptr2->next = ptr1;
    ptr1->next = tmp;
    return ptr2;
}

void sort(Tutor **h, string type)
{

    Tutor **t;
    int i, j, swapornot, count;
    count = countNode();

    if (type == "id")
    {

        for (i = 0; i <= count; i++)
        {
            t = h;
            swapornot = 0;

            for (j = 0; j < count - i - 1; j++)
            {
                Tutor *p1 = *t;
                Tutor *p2 = p1->next;

                if (p1->id > p2->id)
                {

                    *t = swap(p1, p2);
                    swapornot = 1;
                }
                t = &(*t)->next;
            }

            if (swapornot == 0)
            {
                break;
            }
        }
    }

    if (type == "hourlyrate")
    {

        for (i = 0; i <= count; i++)
        {
            t = h;
            swapornot = 0;

            for (j = 0; j < count - i - 1; j++)
            {
                Tutor *p1 = *t;
                Tutor *p2 = p1->next;

                if (p1->hourlyrate > p2->hourlyrate)
                {

                    *t = swap(p1, p2);
                    swapornot = 1;
                }
                t = &(*t)->next;
            }

            if (swapornot == 0)
            {
                break;
            }
        }
    }

    if (type == "rating")
    {

        for (i = 0; i <= count; i++)
        {
            t = h;
            swapornot = 0;

            for (j = 0; j < count - i - 1; j++)
            {
                Tutor *p1 = *t;
                Tutor *p2 = p1->next;

                if (p1->rating > p2->rating)
                {

                    *t = swap(p1, p2);
                    swapornot = 1;
                }
                t = &(*t)->next;
            }

            if (swapornot == 0)
            {
                break;
            }
        }
    }
}

void display(struct Tutor *p)
{

    int i = 1;

    while (p != NULL)
    {

        cout << i << ":" << p->id << " " << p->fname << " " << p->lname << " " << p->datej << " " << p->hourlyrate << " " << p->phone << " " << p->address << " " << p->tuitioncode << " " << p->tuitionname << " " << p->subjectcode << " " << p->subjectname << " " << p->rating << endl;
        p = p->next;
        i++;
    }
    cout << "This is all the list!" << endl;
}

struct Tutor *searchById(int key) // search tutopr record. The user can choose search key from ID and performance rating
{
    Tutor *start = head;
    Tutor *last = NULL;
    do
    {
        if (start == NULL)
        {
            return NULL;
        }
        Tutor *slow = start;
        Tutor *fast = start->next;
        while (fast != last)
        {
            fast = fast->next;
            if (fast != last)
            {
                slow = slow->next;
                fast = fast->next;
            }
        }

        Tutor *mid = slow;
        if (mid == NULL)
        {
            return NULL;
        }
        if (mid->id == key)
        {
            return mid;
        }
        else if (mid->id < sizeofList)
        {
            start = mid->next;
        }
        else
        {
            last = mid;
        }
    } while (last == NULL || last != start);
    return NULL; // When there is no value, return NULL
}

/*struct Tutor *searchByRate(double key) // search tutopr record. The user can choose search key from ID and performance rating
{
    // Does it need sort?

    Tutor *start = head;
    Tutor *last = NULL;
    do
    {
        if (start == NULL)
        {
            return NULL;
        }
        Tutor *slow = start;
        Tutor *fast = start->next;
        while (fast != last)
        {
            fast = fast->next;
            if (fast != last)
            {
                slow = slow->next;
                fast = fast->next;
            }
        }

        Tutor *mid = slow;
        if (mid == NULL)
        {
            return NULL;
        }
        if (mid->rating == key)
        {
            return mid;
            // cout << i << ":" << p->id << " " << p->fname << " " << p->lname << " " << p->datej << p->hourlyrate << " " << p->phone << " " << p->address << " " << p->tuitioncode << p->tuitionname << " " << p->subjectcode << " " << p->subjectname << " " << p->rating << endl;
        }
        else if (mid->rating < sizeofList)
        {
            start = mid->next;
        }
        else
        {
            last = mid;
        }
    } while (last == NULL || last != start);
    return NULL; // When there is no value, return NULL
    // cout<<"THere is no such value";
}*/

void searchByRate(double key) // search tutopr record. The user can choose search key from performance rating
{                             // search all record from the front of the list
    Tutor *current = head;
    while (current != NULL)
    {
        if (current->rating == key)
        {
            cout << current->id << " " << current->fname << " " << current->lname << " " << current->datej << current->hourlyrate << " " << current->phone << " " << current->address << " " << current->tuitioncode << current->tuitionname << " " << current->subjectcode << " " << current->subjectname << " " << current->rating << endl;
        }
        current = current->next;
    }
    cout << "search done here" << endl;

    return; // When there is no value, return NULL
}

void modify(int keyword) // modify tutor record. it takes id as an argument.
{
    Tutor *looker = searchById(keyword); // search the tutor record base on the id
    int id, tuitioncode, subjectcode, hourlyrate;
    string fname, lname, datej, datet, phone, address, tuitionname, subjectname;
    double rating;
    if (looker == NULL)
    {
        cout << "Can't find the id from the list" << endl;
        return;
    }
    else
    {
        cout << "Enter new id :";
        cin >> id;
        looker->id = id;
        cout << "Enter new first name :";
        cin >> fname;
        looker->fname = fname;
        cout << "Enter new last name :";
        cin >> lname;
        looker->lname = lname;
        cout << "Enter new date joined :";
        cin >> datej;
        looker->datej = datej;
        cout << "Enter new date terminated :";
        cin >> datet;
        looker->datet = datet;
        cout << "Enter new hourly pay rate :";
        cin >> hourlyrate;
        looker->hourlyrate = hourlyrate;
        cout << "Enter new phone number :";
        cin >> phone;
        looker->phone = phone;
        cout << "Enter new address :";
        cin >> address;
        looker->address = address;
        cout << "Enter new Tuition code :";
        cin >> tuitioncode;
        looker->tuitioncode = tuitioncode;
        cout << "Enter new tuition name :";
        cin >> tuitionname;
        looker->tuitionname = tuitionname;
        cout << "Enter new subject code :";
        cin >> subjectcode;
        looker->subjectcode = subjectcode;
        cout << "Enter new subject name :";
        cin >> subjectname;
        looker->subjectname = subjectname;
        cout << "Enter new performance rating :";
        cin >> rating;
        looker->rating = rating;
        cout << "Modification Done!" << endl;
        return;
    }
}

bool login(int password) // login function. password is 123456.
{
    bool flag = false;
    if (password == 123456)
    {
        flag = true;
        return flag;
    }
    else
    {
        cout << "Wrong password, please try again!" << endl;
        return flag;
    }
}

int menue() // menue function
{
    int number;
    cout << "1. Add new tutor" << endl;
    cout << "2. Remove a tutor" << endl;
    cout << "3. Sort and Display tutor list" << endl;
    cout << "4. Search a tutor" << endl;
    cout << "5. Modify a tutor" << endl;
    cin >> number;
    return number;
}

int main()
{
    head = NULL;

    Tutor *newnode = createNewNode(1235, "watru", "shinzato", "12/12/2019", "08/02/2022", 70, "12345678", "Okinawa", 01, "momo", 001, "Math", 4.4);
    insert(newnode);
    Tutor *newnode1 = createNewNode(1234, "mike", "higa", "01/01/2019", "09/02/2022", 80, "12345679", "Naha", 02, "kiki", 001, "Math", 4.5);
    insert(newnode1);
    Tutor *newnode2 = createNewNode(1236, "michael", "miya", "02/12/2020", "04/10/2022", 90, "12345677", "Ginowan", 03, "mimi", 002, "English", 3.5);
    insert(newnode2);
    Tutor *newnode3 = createNewNode(1237, "miku", "komesu", "12/09/2019", "11/02/2022", 60, "12345676", "Hutenma", 04, "uiui", 004, "Physics", 4.4);
    insert(newnode3);
    Tutor *newnode4 = createNewNode(1238, "niki", "mochi", "03/12/2020", "07/02/2022", 50, "12345675", "Nago", 05, "yoyo", 003, "Chemistry", 4.7);
    insert(newnode4);

    int password, number;
    cout << "Welcome!, Enter a password here :";
    cin >> password;
    if (login(password)) // if the password is correct, the admin can manipulate the tutor's records.

    {
        int num = 1;
        while (num == 1)
        {
            number = menue();

            if (number == 1) // add
            {
                add();
            }

            if (number == 2) // remove
            {
                int keyword, choice = 1;
                while (choice == 1)
                {
                    cout << "Enter a id of the tutor you want to delete :"; // repeate the function until the end
                    cin >> keyword;
                    remove(keyword);
                    cout << "Do you still want to add a new tutor?"
                         << "1 : Yes, others : No";
                    cin >> choice;
                }
            }

            if (number == 3) // sort and display
            {

                int choice = 1;
                string sorttype;

                while (choice == 1)
                {
                    cout << "Enter a sort type here (id, hourlyrate, rating) :"; // repeate the function until the end
                    cin >> sorttype;
                    sort(&head, sorttype);

                    display(head);
                    cout << "Do you still want to add a new tutor?"
                         << "1 : Yes, others : No";
                    cin >> choice;
                }
            }

            if (number == 4) // search function.
            {
                int choice = 1;
                string keyword;
                struct Tutor *p;
                while (choice == 1)
                {
                    cout << "What would you like to use to search tutor? id or rating? Enter here the keyword :"; // repeate the function
                    cin >> keyword;
                    sort(&head, keyword); // searchById function is using binary search, so before search, sort the list.

                    if (keyword == "id")
                    {
                        int id;
                        cout << "Enter a id :";
                        cin >> id;
                        p = searchById(id);
                        cout << p->id << " " << p->fname << " " << p->lname << " " << p->datej << p->hourlyrate << " " << p->phone << " " << p->address << " " << p->tuitioncode << p->tuitionname << " " << p->subjectcode << " " << p->subjectname << " " << p->rating << endl;
                    }
                    if (keyword == "rating")
                    {
                        double rating;
                        cout << "Enter a rating :";
                        cin >> rating;
                        searchByRate(rating);
                    }
                    cout << "Do you still want to continue to search?"
                         << "1 : Yes, others : No";
                    cin >> choice;
                }
            }

            if (number == 5) // modify
            {
                int choice = 1;
                int key;
                string keyword = "id";
                sort(&head, keyword);

                while (choice == 1)
                {
                    cout << "Enter a id of the tutor here :";
                    cin >> key;
                    modify(key);
                    cout << "Do you still want to add a new tutor?"
                         << "1 : Yes, others : No";
                    cin >> choice;
                }
            }

            cout << "Do you want to continue?"
                 << "1 : Yes, others : No";
            cin >> num;
        }
    }
    return 0;
}