#include "parser.h"

#include "piliterals_string.h"
#include "pistringlist.h"


PIString fromCode(const PIString & in) {
	return in.replacedAll("\\n", '\n')
		.replaceAll("\\r", '\r')
		.replaceAll("\\t", '\t')
		.replaceAll("\\\"", '"')
		.replaceAll("\\'", '\'')
		.replaceAll("\\\\", '\\');
}


void gatherStrings(TSFile::Content & content, const PIString & file, const PIString & file_loc, int & count_all, int & count_new) {
	static const PIStringList methods({"PITranslator::tr", "PITranslator::trNoOp", "piTr", "piTrNoOp"});
	static const PIStringList literals({"_tr", "_trNoOp"});
	PIString source, context;
	int pos = -1, ppos = 0, line = -1;
	int len        = 0;
	auto isCLetter = [](const PIChar c) { return c.isAlpha() || c.isDigit() || c == '_'; };
	auto add       = [&content, file_loc, &count_all, &count_new](const PIString & source, const PIString & context, int line) {
		if (source.isEmpty()) return;
		++count_all;
		if (content.contexts[context].confirm(fromCode(source), file_loc, line)) ++count_new;
		// piCout << "Context = \"" << context << "\", message = \"" << source << "\" (" << file_loc << ":" << line << ")";
	};
	// piCout << "file" << file_loc;
	for (const auto & kw: methods) {
		// piCout << "method" << kw;
		for (;;) {
			source.clear();
			context.clear();

			pos = file.find(kw, pos + 1);
			if (pos < 0) break;
			if (pos > 0) {
				auto pc = file[pos - 1];
				if (isCLetter(pc) || pc == ':') {
					pos += kw.size_s();
					continue;
				}
			}
			pos += kw.size_s();
			if (pos < file.size_s() - 1) {
				auto pc = file[pos];
				if (isCLetter(pc) || pc == ':') {
					pos += kw.size_s();
					continue;
				}
			}
			// piCout << "PITranslator" << pos;

			pos = file.find('(', pos);
			if (pos < 0) break;
			// piCout << "(" << pos;
			pos += 1;

			pos = file.findRange('"', '"', '\\', pos, &len);
			if (pos < 0) break;
			// piCout << "\"" << pos;
			source = file.mid(pos, len);
			pos += len + 1;
			line = file.lineNumber(pos);
			ppos = pos;

			while (pos < file.size_s()) {
				if (!file[pos].isSpace() && file[pos] != '\n' && file[pos] != '\r') break;
				++pos;
			}
			if (pos < file.size_s()) {
				// piCout << "check comma" << file[pos];
				if (file[pos] == ',') {
					pos += 1;
					pos = file.findRange('"', '"', '\\', pos, &len);
					// piCout << "check range" << file.mid(pos, len);
					if (pos >= 0) {
						context = file.mid(pos, len);
						pos += len + 1;
						ppos = pos;
					}
				}
			}

			pos = ppos;
			add(source, context, line);
		}
	}
	for (const auto & kw: literals) {
		// piCout << "literal" << kw;
		pos = -1;
		for (;;) {
			source.clear();
			context.clear();

			pos = file.find('"', pos + 1);
			if (pos < 0) break;
			pos = file.findRange('"', '"', '\\', pos, &len);
			if (pos < 0) break;
			// piCout << "\"" << pos;
			source = file.mid(pos, len);
			pos += len + 1;
			if (file.mid(pos, kw.size_s()) == kw) {
				// piCout << "line" << file.lineNumber(pos);
				pos += kw.size_s();
				if (pos < file.size_s() - 1) {
					auto pc = file[pos];
					if (isCLetter(pc) || pc == ':') {
						continue;
					}
				}
				ppos = pos;
				while (pos < file.size_s()) {
					if (!file[pos].isSpace() && file[pos] != '\n' && file[pos] != '\r') break;
					++pos;
				}
				if (pos < file.size_s()) {
					// piCout << "check comma" << file[pos];
					if (file[pos] == '(') {
						pos += 1;
						pos = file.findRange('"', '"', '\\', pos, &len);
						// piCout << "check range" << file.mid(pos, len);
						if (pos >= 0) {
							context = file.mid(pos, len);
							pos += len + 1;
							ppos = pos;
						}
					}
				}
				pos = ppos;
				if (source.isEmpty()) continue;
				line = file.lineNumber(pos);
				add(source, context, line);
			}
		}
	}
}
