#include "text_editor.h"

#include "TextEditor.h"

#include <string>

namespace fn {

struct TextEditorState {
    ::TextEditor editor;     // vendor type, oculto detras del PIMPL
    std::string  cached_text; // buffer estable para text_editor_get_text()
    bool         dirty = false;
};

static const ::TextEditor::LanguageDefinition& lang_def(CodeLang lang) {
    switch (lang) {
        case CodeLang::GLSL: return ::TextEditor::LanguageDefinition::GLSL();
        case CodeLang::SQL:  return ::TextEditor::LanguageDefinition::SQL();
        case CodeLang::Cpp:  return ::TextEditor::LanguageDefinition::CPlusPlus();
        case CodeLang::Generic:
        default:
            return ::TextEditor::LanguageDefinition::CPlusPlus();
    }
}

TextEditorState* text_editor_create(CodeLang lang) {
    auto* s = new TextEditorState();
    s->editor.SetLanguageDefinition(lang_def(lang));
    s->editor.SetShowWhitespaces(false);
    return s;
}

void text_editor_destroy(TextEditorState* state) {
    delete state;
}

void text_editor_set_text(TextEditorState* state, const char* text) {
    if (!state || !text) return;
    state->editor.SetText(text);
    state->cached_text = text;
    state->dirty = false;
}

const char* text_editor_get_text(TextEditorState* state) {
    if (!state) return "";
    state->cached_text = state->editor.GetText();
    // El editor anade siempre un '\n' final; lo dejamos para preservar
    // la semantica del vendor (es lo que devuelve GetText()).
    return state->cached_text.c_str();
}

bool text_editor_render(TextEditorState* state, const char* label, ImVec2 size) {
    if (!state) return false;
    state->editor.Render(label, size, true);
    const bool changed = state->editor.IsTextChanged();
    if (changed) state->dirty = true;
    return changed;
}

bool text_editor_is_dirty(const TextEditorState* state) {
    return state ? state->dirty : false;
}

void text_editor_clear_dirty(TextEditorState* state) {
    if (state) state->dirty = false;
}

} // namespace fn
