#include <spdlog/spdlog.h>
#include "../../utils/text_coordinates.hpp"
#include "./text_document.hpp"

namespace lsp::service::document
{
    TextDocument::TextDocument(const protocol::TextDocumentItem& item) :
        item_(item) {}

    void TextDocument::ApplyChange(const protocol::TextDocumentContentChangeEvent& change)
    {
        if (IsFullDocumentUpdate(change, item_.text))
        {
            item_.text = change.text;
            spdlog::debug("Full Document update for: {}", item_.uri);
        }
        else
        {
            protocol::uinteger start_offset = utils::text_coordinates::ToOffset(change.range.start, item_.text);
            protocol::uinteger end_offset = utils::text_coordinates::ToOffset(change.range.end, item_.text);
            item_.text.replace(start_offset, end_offset - start_offset, change.text);
            spdlog::debug("Incremental update for: {}", item_.uri);
        }
    }

    void TextDocument::SetVersion(protocol::integer version)
    {
        item_.version = version;
    }

    const protocol::string& TextDocument::GetContent() const
    {
        return item_.text;
    }

    const protocol::DocumentUri& TextDocument::GetUri() const
    {
        return item_.uri;
    }

    protocol::integer TextDocument::GetVersion() const
    {
        return item_.version;
    }

    bool TextDocument::IsFullDocumentUpdate(const protocol::TextDocumentContentChangeEvent& change, const protocol::string& current_content)
    {
        if (change.range.start.line == 0 && change.range.start.character == 0)
        {
            protocol::uinteger line_count = 0;
            for (size_t i = 0; i < current_content.length(); ++i)
            {
                if (current_content[i] == '\n')
                    line_count++;
            }
            if (change.range.end.line >= line_count)
                return true;
        }
        return false;
    }

}
