#pragma once

#include "lumacs/editor_core.hpp"
#include "lumacs/window.hpp"
#include "lumacs/theme.hpp"

#include <gtkmm.h>
#include <pangomm.h>
#include <memory>
#include <optional>

namespace lumacs {

// Forward declarations
class EditorCore;
class Window;

// Constants for padding
static constexpr double PADDING_LEFT = 8.0;
static constexpr double PADDING_TOP = 8.0;
static constexpr double PADDING_RIGHT = 8.0;
static constexpr double PADDING_BOTTOM = 8.0;

class GtkRenderer {
public:
    GtkRenderer(EditorCore& core, Gtk::DrawingArea& main_drawing_area);

    void initialize_font_metrics();
    void apply_face_attributes(Pango::AttrList& attr_list, const FaceAttributes& face, int start_index, int end_index);
    std::optional<Position> resolve_screen_pos(std::shared_ptr<Window> window, double x, double y);

    void on_draw(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height,
                 std::shared_ptr<Window> active_window_cache, bool cursor_visible_state);

    void draw_window(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height,
                     std::shared_ptr<Window> window, Gtk::DrawingArea* widget,
                     std::shared_ptr<Window> active_window_cache, bool cursor_visible_state);

    void render_modeline_for_window(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height,
                                   std::shared_ptr<Window> window,
                                   std::shared_ptr<Window> active_window_cache);
    
    void render_minibuffer(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height);

    /// @brief Gets the screen coordinates and dimensions of the minibuffer area.
    /// @param x Output parameter for the X coordinate.
    /// @param y Output parameter for the Y coordinate.
    /// @param width Output parameter for the width.
    /// @param height Output parameter for the height.
    /// @return True if the coordinates could be determined, false otherwise.
            bool get_minibuffer_coords(int& x, int& y, int& width, int& height) const;
        
        private:
            struct LineCacheEntry {
                std::string text_content;
                std::vector<StyledRange> styles; // Check if styles changed
                Cairo::RefPtr<Cairo::ImageSurface> surface;
                int width = 0;
                int height = 0;
            };    
        // Map Window ID (or ptr) -> (Line Index -> Cache Entry)
        std::unordered_map<Window*, std::unordered_map<size_t, LineCacheEntry>> render_cache_;
    
        EditorCore& core_;
        Gtk::DrawingArea& main_drawing_area_;

    Pango::FontDescription font_desc_;
    bool font_initialized_ = false;
    double char_width_ = 0;
    double line_height_ = 0;
    double ascent_ = 0;
};

} // namespace lumacs
