#include <iostream>
#include <vector>
#include <algorithm>
#include <stdexcept>

using namespace std;

#include "tournament.h"
#include "restaurant.h"
#include "io.h"

ostream & operator<<(ostream & os, vector<restaurant> & v) {
    for(auto i: v) {
        os << i << endl;
    }
    return os;
}

ostream & operator<<(ostream & os, tournament & t){
    os << "[";
    for(unsigned int i = 0; i < t.restaurants.size(); i++) {
        if(i == t.restaurants.size() - 1) {
            os << t.restaurants[i];
        }
        else {
            os << t.restaurants[i]<< " ,";
        }
    }
    os << "]";
    return os;
}

bool tournament::populate_restaurants(string filename) {
    try {
        restaurants = parse_file(filename);
        return true;
    }
    catch(runtime_error e) {
        cerr << e.what() << endl;
        return false;
    }
}

bool tournament::already_in(string name) {
    for(unsigned int i = 0; i < restaurants.size(); i++) {
        if(restaurants[i].name == name) {
            return true;
        }
    }
    return false;
} 

void tournament::add_restaurants() {
    string name;
    int score = 0;
    cout << "name" << endl;
    cin.ignore();
    getline(cin, name);
    if(not already_in(name)) {
        restaurants.push_back(restaurant(name, score));
    }
}

void tournament::remove_restaurants() {
    string name;
    cout << "name" << endl;
    cin.ignore();
    getline(cin, name);
    if(already_in(name)) {
        for(unsigned int i = 0; i < restaurants.size(); i++) {
            if(restaurants[i].name == name){
                restaurants.erase(restaurants.begin() + i);
            }
        }
    }
}

void tournament::shuffle() {
    random_shuffle(restaurants.begin(), restaurants.end());
}

int round_counter(int current_size) {
    int round;
    if(current_size == 32) {
        round = 5;
    }
    if(current_size == 16) {
        round = 4;
    }
    else if(current_size == 8) {
        round = 3;
    }
    else if(current_size == 4) {
        round = 2;
    }
    else if(current_size == 2) {
        round =1;
    }
    return round;
}

int match_counter(int current_size) {
    int match;
    if(current_size == 32) {
        match = 16;
    }
    if(current_size == 16) {
        match = 8;
    }
    else if(current_size == 8) {
        match = 4;
    }
    else if(current_size == 4) {
        match = 2;
    }
    else if(current_size == 2) {
        match =1;
    }
    return match;
}

bool tournament::start_tournament(){
    if(not verify_size()) {
        cout << "not 2^n" << endl;
        return false;
    }
    bool temp_bool = true;
    bool tourn_running = true;
    cin.ignore();
    string name;
    int match = match_counter(restaurants.size());
    int round = round_counter(restaurants.size());
    int current_round = 1;
    vector<restaurant> temp_array;
    while(tourn_running == true) {
        int current_match = 1;
        temp_bool = true;
        cin.ignore();
        for(unsigned int i = 0; i < restaurants.size(); i += 2) {
            while(temp_bool == true) {
                cout << "which restaurant: " << restaurants[i] << " or " << restaurants[i + 1] << endl;
                cout << "match " << current_match << "/" << match << " Round "
                    << current_round << "/" << round << endl;
                getline(cin, name);
                if(name == restaurants[i].name or name == restaurants[i + 1].name) {
                    if(name == restaurants[i].name) {
                        restaurants[i].score++;
                        temp_array.push_back(restaurants[i]);
                        losers.push_back(restaurants[i+1]);
                    }
                    else {
                        restaurants[i+1].score++;
                        temp_array.push_back(restaurants[i + 1]);
                        losers.push_back(restaurants[i]);
                    }
                    temp_bool = false;
                    current_match++;
                }
                else {
                    cout << "invalid response " << name << endl;
                }
            }
            temp_bool = true;
        }
        while(temp_bool == true) {
            for(unsigned int i = 0; i < temp_array.size(); i++) {
                restaurants[i] = temp_array[i];
            }
            for(unsigned int i = 0; i < temp_array.size(); i++){
                restaurants.pop_back();
            }
            if(restaurants.size() == 1) {
                losers.push_back(restaurants[0]);
                cout << "this is the winner " << restaurants[0] << endl;
                restaurants = losers;
                return true;
            }
            else {
                cout << "next round of tournament" << endl;
                temp_bool = false;
            }
        }
        temp_array.clear();
        match = match/2;
        current_round++;
    }
    return false;
}

bool tournament::verify_size() {
    int r = restaurants.size();
    if(r == 2 or r == 4 or r == 8 or r == 16 or r == 32 or r == 64) {
        return true;
    }
    return false;
}
