#include "UciParser.h"
#include <sstream>

#include "ChessGame.h"

using namespace std;


const std::map<std::string, UciParser::CommandHandler> UciParser::commandHandlers = {
    {"uci",         &UciParser::uci },
    {"debug",       &UciParser::debug },
    {"isready",     &UciParser::isready },
    {"setoption",   &UciParser::setoption },
    {"register",    &UciParser::doNothing },
    {"ucinewgame",  &UciParser::ucinewgame },
};


int UciParser::parse(istream& in, ostream& out)
{
    while (!in.eof()) {
        string line;
        getline(in, line);
        executeLine(line);
    }
    return 0;
}


int UciParser::executeLine(const string& line)
{
    stringstream s{ line };
    string token;
    string command;
    vector<string> args;
    s >> command;
    while (s >> token) {
        args.push_back(std::move(token));
    }
    return executeCommand(command, args);
}


int UciParser::executeCommand(const string& command,
    const vector<string>& args)
{
    try {
        CommandHandler ch = commandHandlers.at(command);
        (this->*ch)(args);
        return 0;
    }
    catch (out_of_range& oor) {
        // no handler for command -> invalid command
        return 1;
    }
}

void UciParser::sendCommand(const std::string& command,
    const std::vector<std::string>& args)
{
    cout << command;
    std::for_each(args.begin(), args.end(), [] (auto& x) { cout << " " << x; });
}


void UciParser::uci(const std::vector<std::string>& args)
{
    sendCommand(UCIOK);
}


void UciParser::debug(const std::vector<std::string>& args)
{
    // not yet implemented
}


void UciParser::isready(const std::vector<std::string>& args)
{
    sendCommand(READYOK);
}


void UciParser::setoption(const std::vector<std::string>& args)
{
}


void UciParser::ucinewgame(const std::vector<std::string>& args)
{
}


void UciParser::doNothing(const std::vector<std::string>& args)
{
    // explicitly do nothing
    return;
}