#include "./text_coordinates.hpp"

namespace lsp::service::utils::text_coordinates
{

    protocol::uinteger ToOffset(const protocol::Position& position, const protocol::string& content)
    {
        protocol::uinteger offset = 0;
        protocol::uinteger current_line = 0;

        while (offset < content.length() && current_line < position.line)
        {
            if (content[offset] == '\n')
                current_line++;
            offset++;
        }
        if (offset >= content.length())
            return content.length();

        protocol::uinteger current_char = 0;
        while (offset < content.length() && current_char < position.character)
        {
            if (content[offset] == '\n')
                break;
            unsigned char ch = static_cast<unsigned char>(content[offset]);
            if ((ch & 0x80) == 0)
                offset += 1;
            else if ((ch & 0xE0) == 0xC0)
                offset += 2;
            else if ((ch & 0xF0) == 0xE0)
                offset += 3;
            else if ((ch & 0xF8) == 0xF0)
                offset += 4;
            else
                offset += 1;
            current_char++;
        }
        return std::min(offset, static_cast<protocol::uinteger>(content.length()));
    }

    TSPoint ToPoint(const protocol::Position& position)
    {
        return TSPoint{
            .row = static_cast<uint32_t>(position.line),
            .column = static_cast<uint32_t>(position.character)
        };
    }

    TSPoint CalculateEndPoint(const protocol::string& text, TSPoint start)
    {
        TSPoint end = start;
        for (char c : text)
        {
            if (c == '\n')
            {
                end.row++;
                end.column = 0;
            }
            else
            {
                end.column++;
            }
        }
        return end;
    }
}
