#include "lumacs/gtk_completion_popup.hpp"

#ifdef LUMACS_WITH_GTK

#include <gtkmm/label.h>
#include <gtkmm/box.h>
#include <gtkmm/cssprovider.h>
#include <gtkmm/stylecontext.h>

namespace lumacs {

// Helper to create a styled Gtk::Label for candidate description
Gtk::Widget* create_candidate_row_widget(const CompletionCandidate& candidate) {
    auto hbox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 6);

    auto text_label = Gtk::make_managed<Gtk::Label>(candidate.text, Gtk::Align::START);
    text_label->set_hexpand(true); // Allow text to expand

    auto desc_label = Gtk::make_managed<Gtk::Label>(candidate.description, Gtk::Align::END);
    desc_label->set_hexpand(true); // Allow description to expand
    desc_label->set_halign(Gtk::Align::END);

    // Apply a subtle style to description for differentiation
    auto css_provider = Gtk::CssProvider::create();
    css_provider->load_from_data("label.completion-description { color: #888; font-size: 0.9em; margin-left: 12px; }");
    desc_label->get_style_context()->add_provider(css_provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
    desc_label->get_style_context()->add_class("completion-description");

    hbox->append(*text_label);
    hbox->append(*desc_label);

    return hbox;
}

GtkCompletionPopup::GtkCompletionPopup()
    : Gtk::Popover(), // Inherit from Gtk::Popover
      active_index_(0) {
    
    // Set properties for the popup
    // Gtk::Popover automatically adjusts size based on content.
    // No explicit decorated, resizable, hide_on_close needed for popovers.
    set_child(list_scrolled_window_); // Set scrolled window as child

    list_scrolled_window_.set_child(list_box_);
    list_scrolled_window_.set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC);
    list_scrolled_window_.set_propagate_natural_width(true);
    list_scrolled_window_.set_propagate_natural_height(true);

    list_box_.set_selection_mode(Gtk::SelectionMode::SINGLE);
    list_box_.set_activate_on_single_click(true); // Activate on single click
    list_box_.signal_row_activated().connect(sigc::mem_fun(*this, &GtkCompletionPopup::on_row_activated));

    // Add CSS for a border and padding
    auto css_provider = Gtk::CssProvider::create();
    css_provider->load_from_data(
        "popover.lumacs-completion-popup {"
        "   border: 1px solid @border_color;"
        "   background-color: @theme_bg_color;"
        "}"
        "listbox.lumacs-completion-listbox {"
        "   padding: 0px;"
        "}"
        "listboxrow.lumacs-completion-row {"
        "   padding: 4px 8px;"
        "}"
        "listboxrow.lumacs-completion-row:selected {"
        "   background-color: @accent_bg_color;"
        "   color: @accent_fg_color;"
        "}"
    );
    get_style_context()->add_provider(css_provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
    get_style_context()->add_class("lumacs-completion-popup");
    list_box_.get_style_context()->add_class("lumacs-completion-listbox");

    /*
    add_action("completion.select-next", sigc::mem_fun(*this, &GtkCompletionPopup::select_next));
    add_action("completion.select-previous", sigc::mem_fun(*this, &GtkCompletionPopup::select_previous));
    */

    // This is necessary for the popup to be destroyed when hidden, rather than just hidden.
    // However, for popovers, set_autohide() often handles its own lifetime.
}

GtkCompletionPopup::~GtkCompletionPopup() {
    // No specific cleanup needed for GTKmm objects, they are managed by Glib::make_managed or Gtk::Window
}

void GtkCompletionPopup::show_popup(const std::vector<CompletionCandidate>& candidates, size_t active_index, Gtk::Widget& relative_to, int x_offset, int y_offset) {
    candidates_ = candidates;
    active_index_ = active_index;
    update_list();

    set_parent(relative_to);
    
    // Calculate the point to which the popover should be pointing.
    // It's usually below the widget, aligned to its left or a specific sub-rectangle.
    // For now, let's point below the widget.
    Gdk::Rectangle rect;
    rect.set_x(x_offset);
    rect.set_y(y_offset);
    rect.set_width(1); // Small width, it's a point
    rect.set_height(1); // Small height, it's a point

    set_pointing_to(rect);
    set_autohide(true); // Popover will hide when focus is lost outside.
    
    popup();
}

void GtkCompletionPopup::hide_popup() {
    candidates_.clear();
    active_index_ = 0;
    list_box_.remove_all();
    popdown();
}

void GtkCompletionPopup::update_list() {
    list_box_.remove_all();
    for (const auto& candidate : candidates_) {
        auto row = Gtk::make_managed<Gtk::ListBoxRow>();
        row->set_child(*create_candidate_row_widget(candidate));
        row->get_style_context()->add_class("lumacs-completion-row");
        list_box_.append(*row);
    }
    set_active_row(active_index_);
    list_box_.show();
}

void GtkCompletionPopup::set_active_row(size_t index) {
    if (index < candidates_.size()) {
        Gtk::ListBoxRow* row = list_box_.get_row_at_index(static_cast<int>(index));
        if (row) {
            list_box_.select_row(*row);
            // row->scroll_to_row(); // Ensure the selected row is visible (TODO: Fix for GTK4)
            active_index_ = index;
        }
    }
}

void GtkCompletionPopup::select_next() {
    if (candidates_.empty()) return;
    active_index_ = (active_index_ + 1) % candidates_.size();
    set_active_row(active_index_);
}

void GtkCompletionPopup::select_previous() {
    if (candidates_.empty()) return;
    if (active_index_ == 0) {
        active_index_ = candidates_.size() - 1;
    } else {
        active_index_--;
    }
    set_active_row(active_index_);
}

std::optional<CompletionCandidate> GtkCompletionPopup::get_selected_candidate() const {
    if (!candidates_.empty()) {
        return candidates_[active_index_];
    }
    return std::nullopt;
}

void GtkCompletionPopup::on_row_activated(Gtk::ListBoxRow* row) {
    active_index_ = static_cast<size_t>(row->get_index());
    if (auto selected = get_selected_candidate()) {
        signal_candidate_selected_.emit(selected.value());
    }
    hide_popup();
}

GtkCompletionPopup::type_signal_candidate_selected GtkCompletionPopup::signal_candidate_selected() {
    return signal_candidate_selected_;
}

GtkCompletionPopup::type_signal_cancelled GtkCompletionPopup::signal_cancelled() {
    return signal_cancelled_;
}

} // namespace lumacs

#endif // LUMACS_WITH_GTK
