#include <sstream>
#include <vector>
#include <chrono>

#include "api.h"
#include "result.h"
#include "lexer.h"
#include "parser.h"
#include "time.h"
#include "config.h"

#define TABWIDTH 4

bool debug;
std::chrono::high_resolution_clock::time_point start;
std::chrono::high_resolution_clock::time_point end;

std::string wrapText(std::string text, size_t width) {
	std::string result;
    size_t currentLineLength = 0;
    size_t wordStart = 0;
    
    size_t preservedSpaceCount = 0;
    for (size_t i = 0; i < text.length(); ++i) {
		if (text[i] == '\t') {
            preservedSpaceCount += TABWIDTH;
		} else if (!std::isalnum(text[i])) {
            preservedSpaceCount++;
        } else {
            wordStart = i; 
            break;
        }
    }
    result += text.substr(0, wordStart);
    currentLineLength = preservedSpaceCount;

    for (size_t i = wordStart; i < text.length(); ++i) {
        if (text[i] == ' ' || i == text.length() - 1) {
            size_t wordEnd = (i == text.length() - 1) ? i + 1 : i; // Handle the last word
            size_t wordLength = wordEnd - wordStart;
            if (currentLineLength + wordLength > width) {
                result += '\n';
                result.append(preservedSpaceCount / TABWIDTH, '\t');
                result.append(preservedSpaceCount % TABWIDTH, ' ');
                currentLineLength = preservedSpaceCount;
            }
            result += text.substr(wordStart, wordLength) + ' ';
            currentLineLength += wordLength + 1;
            wordStart = i + 1;
        }
	}
    return result;
}

std::string escapeText(std::string text) {
	std::stringstream ss;
	for (auto c: text) {
		switch(c) {
			case '\\':
				ss << "\\\\";
				break;
			case '[':
				ss << "\\[";
				break;
			case ']':
				ss << "\\]";
				break;
			case '-':
				ss << "\\-";
				break;
			case '^':
				ss << "\\^";
				break;
			case ':':
				ss << "\\:";
				break;
			case '>':
				ss << "\\>";
				break;
			case '+':
				ss << "\\+";
				break;
			default:
				ss << c;
				break;
		}
	}
	return ss.str();
}

Result<ParseInfo> transpile(std::string fileContent, bool isDebug) {
	start = std::chrono::high_resolution_clock::now();
	end = std::chrono::high_resolution_clock::now();
	debug = isDebug;

	auto lexRes = tokenizeMdem(fileContent);
	auto tokens = lexRes.value;
	if (lexRes.error.length() > 0) {
		return {
			{},
			std::format(
				"Lexical analysis error: {}",
				lexRes.error
			),
			lexRes.row,
			lexRes.column
		};
	}

	auto parseRes = parseQuestions(tokens);
	auto questions = parseRes.value;
	if (parseRes.error.length() > 0) {
		return {
			{},
			std::format(
				"Parsing error: {}",
				parseRes.error
			),
			parseRes.row,
			parseRes.column
		};
	}

	end = std::chrono::high_resolution_clock::now();
	showTime("Transpilation time");
	return {questions};
}
