#include "test.h"

#include "base_line_provider.h"
#include "line.h"

TEST_CASE("store and fetch") {
	Line l(string("hello"));
	CHECK(l.length() == 5);
	CHECK(l.view() == l.get());
	CHECK(l.view() == "hello");
}

TEST_CASE("update and revert") {
	Line l(string("hello"));
	l.set("updated");
	CHECK(l.get() == "updated");
	CHECK(l.view() == "updated");
	CHECK(l.length() == 7);
	l.revert();
	CHECK(l.get() == "hello");
	CHECK(l.view() == "hello");
	CHECK(l.length() == 5);
}

TEST_CASE("double update and revert") {
	Line l(string("hello"));
	l.set("updated");
	CHECK(l.get() == "updated");
	CHECK(l.view() == "updated");
	CHECK(l.length() == 7);
	l.set("updated again");
	CHECK(l.get() == "updated again");
	CHECK(l.view() == "updated again");
	CHECK(l.length() == 13);
	l.revert();
	CHECK(l.get() == "hello");
	CHECK(l.view() == "hello");
	CHECK(l.length() == 5);
}

TEST_CASE("ansi") {
	string s = "\x1b[4mhello\x1b[24m";
	auto x = BaseLineProvider::get_string_and_format(s);
	CHECK(x.first == "hello");
	CHECK(x.second == "@@@@@");
}

TEST_CASE("ansi colour") {
	string s = "\x1b[34mhello\x1b[37mthere";
	auto x = BaseLineProvider::get_string_and_format(s);
	CHECK(x.first == "hellothere");
	CHECK(x.second == string("\4\4\4\4\4\0\0\0\0\0", 10));
}

TEST_CASE("ansi colour and bold") {
	string s = "\x1b[34mhello\x1b[4mthere";
	auto x = BaseLineProvider::get_string_and_format(s);
	CHECK(x.first == "hellothere");
	CHECK(x.second == "\4\4\4\4\4DDDDD");
}

/* check conversion from string and format, to line, to formatstring */
void check_line_to_formatline(const string& str, const string& fmt) {
	// this test won't work if there is a tab in string, because the
	// formatstring will expand it. make another test for that
	CHECK(str.find('\t') == string::npos);
	Line line(str, fmt);
	FormatString fs;
	size_t ret = line.render(100, true, nullopt, 0, set<size_t>(), nullptr, &fs);
	CHECK(ret == fs.size());
	CHECK(fmt.size() == fs.size());
	CHECK(fmt.size() == str.size());
	for (size_t i = 0; i < str.size(); ++i) {
		CHECK(fs.code(i) == (int) fmt[i]);
	}
}

TEST_CASE("ansi giterror") {
	string s =
	    "\x1b\x5b\x33\x32\x6d\x2b\x1b\x5b\x6d\x09\x1b\x5b\x33\x32\x6d\x73";
	s += "\x74\x72\x69\x6e\x67\x20\x73\x20\x3d\x20\x22\x5c\x78\x31\x62\x5b";
	s += "\x33\x36\x6d\x40\x40\x20\x2d\x31\x35\x31";
	auto x = BaseLineProvider::get_string_and_format(s);
	CHECK(x.second[0] == 2);
	Line line(x.first, x.second);
	FormatString fs;
	size_t ret = line.render(100, true, nullopt, 0, set<size_t>(), nullptr, &fs);
	CHECK(ret == fs.size());
	CHECK(fs.code(0) == 2);
}

TEST_CASE("ansi gitline") {
	string s = "\x1b[36m@@ -151,6 +152,7 @@ \x1b[m  \x1b[mprotected: \x1b[m";
	auto x = BaseLineProvider::get_string_and_format(s);
	CHECK(x.first == "@@ -151,6 +152,7 @@   protected: ");
	string fmt(x.first.length(), '\6');
	CHECK(x.second.length() == x.first.length());
	fmt[2] = '\0';
	fmt[9] = '\0';
	fmt[16] = '\0';
	fmt[19] = '\0';
	fmt[20] = '\0';
	fmt[21] = '\0';
	fmt[32] = '\0';
	CHECK(x.second == fmt);
	check_line_to_formatline(x.first, x.second);
	s = "\x1b[32m+ \x1b[m \x1b[32mcolour \x1b[m";
	x = BaseLineProvider::get_string_and_format(s);
	CHECK(x.first == "+  colour ");
	CHECK(x.second.length() == x.first.length());
	fmt = string(x.first.length(), '\2');
	fmt[1] = '\0';
	fmt[2] = '\0';
	fmt[9] = '\0';
	CHECK(x.second == fmt);
	check_line_to_formatline(x.first, x.second);
}

TEST_CASE("no backspace") {
	string s = "hello";
	auto x = BaseLineProvider::get_string_and_format(s);
	CHECK(x.first == s);
	CHECK(x.second == string("\0\0\0\0\0", 5));
}

TEST_CASE("backspace underline") {
	string s = "he_\bl_\blo";
	string f = string("\0\0\64\64\0", 5);
	auto x = BaseLineProvider::get_string_and_format(s);
	CHECK("hello" == x.first);
	CHECK(f == x.second);
}

TEST_CASE("backspace bold") {
	BaseLineProvider bp(nullptr);
	string s = "hel\bll\blo\bo";
	string f = string("\0\0\32\32\32", 5);
	auto x = BaseLineProvider::get_string_and_format(s);
	CHECK("hello" == x.first);
	CHECK(f == x.second);
}

TEST_CASE("tabstops") {
	list<size_t> l = {0, 4, 9};
	Line line(string("this\tthat\twheeeee"));
	CHECK(l == line.tabstops('\t'));
}

TEST_CASE("tabstops csv") {
	list<size_t> l = {0, 4, 9};
	Line line(string("this,that,wheeeee"));
	CHECK(l == line.tabstops(','));
	CHECK(list<size_t>{0} == line.tabstops('\t'));
}

TEST_CASE("tabstops quote") {
	list<size_t> l = {0, 4, 12};
	Line line(string("this,\"th,at\",last"));
	CHECK(l == line.tabstops(','));
}

TEST_CASE("tabstops quote escape") {
	TabData tab_data;
	list<size_t> l = {0, 4, 18};
	Line line(string("this,\"th,at\\\"more\",last"));
	CHECK(l == line.tabstops(','));
	line.measure_tabs(',', &tab_data);
	CHECK(tab_data.width(0) == 5);
	CHECK(tab_data.width(1) == 15);
	CHECK(tab_data.width(2) == 0);
}


