#include "gtest/gtest.h"
#include "CommandParser.h"
#include <iostream>

typedef std::string ss;

void dump(const std::vector<EncodedString> & v)
{
    for (auto s : v)
    {
        std::cerr << " \"" << ss((const char *)&s[0], s.size()) << "\"" << std::endl;
    }
}

#define compare_parsed(expected, results) \
    compare_parsed_(expected, results, __LINE__)

void compare_parsed_(const std::vector<EncodedString> & expected,
                    const std::vector<EncodedString> & results,
                    int line)
{
    if (expected != results)
    {
        std::cerr << "Line " << line << " unexpected parsed result:" << std::endl;
        std::cerr << "Expected:" << std::endl;
        dump(expected);
        std::cerr << "Actual:" << std::endl;
        dump(results);
    }
    EXPECT_EQ(expected, results);
}

TEST(CommandParser_parse, parses_a_basic_command)
{
    EncodedString command("w /home/josh/file");
    CommandParser cp;
    EXPECT_TRUE(cp.parse(command));
    compare_parsed(std::vector<EncodedString>({
        ss("w"),
        ss("/home/josh/file"),
        }), cp.args());
}

TEST(CommandParser_parse, parses_a_command_with_quoted_arguments)
{
    EncodedString command("echo 'Hello There'\" World!\" a'b'c d\"e\"f ' ' \"\" 1 2 3\n");
    CommandParser cp;
    EXPECT_TRUE(cp.parse(command));
    compare_parsed(std::vector<EncodedString>({
        ss("echo"),
        ss("Hello There World!"),
        ss("abc"),
        ss("def"),
        ss(" "),
        ss(""),
        ss("1"),
        ss("2"),
        ss("3"),
        }), cp.args());
}

TEST(CommandParser_parse, parses_a_command_with_escaped_characters)
{
    EncodedString command("  echo \\  ' \\' a '  \"b \\\" c\" \\\\too\n");
    CommandParser cp;
    EXPECT_TRUE(cp.parse(command));
    compare_parsed(std::vector<EncodedString>({
        ss("echo"),
        ss(" "),
        ss(" ' a "),
        ss("b \" c"),
        ss("\\too"),
        }), cp.args());
}

TEST(CommandParser_parse, fails_to_parse_with_an_unterminated_escape_sequence)
{
    EncodedString command("echo hi\\");
    CommandParser cp;
    EXPECT_FALSE(cp.parse(command));
    EXPECT_EQ("Unterminated escape sequence", cp.parse_error());
}

TEST(CommandParser_parse, fails_to_parse_with_an_unterminated_quoted_region)
{
    EncodedString command("echo Bob's Golf Bag");
    CommandParser cp;
    EXPECT_FALSE(cp.parse(command));
    EXPECT_EQ("Unterminated quoted region", cp.parse_error());
}
