#include <Utilities/Parse.hpp>
#include <sstream>

std::vector<std::string> Parse::tokenize(const std::string &cmdline)
{
    std::vector<std::string> tokens;
    std::string currentToken;
    char currentQuote = 0;
    bool escape = false;

    for (char c : cmdline)
    {
        if (escape)
        {
            currentToken += c;
            escape = false;
        }
        else if (c == '\\')
        {
            escape = true;
        }
        else if (c == '\'' || c == '\"')
        {
            if (currentQuote == c)
            {
                // Closing the current quote.
                currentQuote = 0;
            }
            else if (currentQuote == 0)
            {
                // Opening a new quote.
                currentQuote = c;
            }
            else
            {
                // Nested, treat as normal char.
                currentToken += c;
            }
        }
        else if (isspace(c) && currentQuote == 0)
        {
            if (!currentToken.empty())
            {
                tokens.push_back(currentToken);
                currentToken.clear();
            }
        }
        else
        {
            currentToken += c;
        }
    }

    if (!currentToken.empty())
    {
        tokens.push_back(currentToken);
    }

    return tokens;
}

bool Parse::fromString(const std::string &str, std::string &out)
{
    out = str;
    return true;
}

bool Parse::fromString(const std::string &str, int &out)
{
    if (str.empty())
    {
        return false;
    }

    std::istringstream iss(str);
    iss >> out;

    if (iss.fail() || !iss.eof())
    {
        return false;
    }

    return true;
}

bool Parse::fromString(const std::string &str, bool &out)
{
    if (str == "on" || str == "true" || str == "yes")
    {
        out = true;
        return true;
    }

    if (str == "off" || str == "false" || str == "no")
    {
        out = false;
        return true;
    }

    return false;
}

bool Parse::fromTokens(TokenIterator current, TokenIterator end)
{
    return current == end;
}

bool Parse::fromTokens(TokenIterator current, TokenIterator end, std::vector<std::string> &restOut)
{
    while (current != end)
    {
        restOut.push_back(*current);
        ++current;
    }

    return true;
}