// class that handles low-level rendering operations, such as drawing pixels and shapes to the display.
// This class is framework-agnostic and focuses solely on manipulating a 1-bit per pixel buffer.
// Constructor Args:
// uint8_t* buffer: Pointer to the bit buffer
// int width: Display width in pixels
// int height: Display height in pixels

#ifndef LOW_LEVEL_RENDER_H
#define LOW_LEVEL_RENDER_H

#include <cstdint>
#include <string>
#include <vector>

// Font class that holds font data and dimensions
class Font {
private:
    const unsigned char* data;
    int num_chars;
    int bytes_per_char;
    int char_height;

public:
    Font(const unsigned char* font_data, int num_chars, int bytes_per_char, int char_height)
        : data(font_data), num_chars(num_chars), bytes_per_char(bytes_per_char), 
          char_height(char_height) {}

    const unsigned char* get_data() const { return data; }
    int get_num_chars() const { return num_chars; }
    int get_bytes_per_char() const { return bytes_per_char; }
    int get_char_height() const { return char_height; }
    
    // Get a specific character's data
    const unsigned char* get_char_data(int char_index) const {
        if (char_index < 0 || char_index >= num_chars) return nullptr;
        return data + (char_index * bytes_per_char);
    }
};

// Font extern declarations
extern const unsigned char font_5x5[96][6];
extern const unsigned char font_7linedigital[96][4];
extern const unsigned char font_acme_5_outlines[96][6];
extern const unsigned char font_aztech[96][6];
extern const unsigned char font_BMplain[96][6];
extern const unsigned char font_BMSPA[96][8];
extern const unsigned char font_Blokus[96][6];
extern const unsigned char font_bubblesstandard[96][7];
extern const unsigned char font_Commo_Monospaced[96][8];
extern const unsigned char font_crackers[96][6];
extern const unsigned char font_formplex12[96][8];
extern const unsigned char font_haiku[96][6];
extern const unsigned char font_HISKYF21[96][6];
extern const unsigned char font_homespun[96][7];
extern const unsigned char font_HUNTER[96][8];
extern const unsigned char font_m38[96][8];
extern const unsigned char font_Minimum[96][6];
extern const unsigned char font_Minimum_1[96][7];
extern const unsigned char font_pzim3x5[96][3];
extern const unsigned char font_Raumsond[96][5];
extern const unsigned char font_renew[96][7];
extern const unsigned char font_sloth[96][6];
extern const unsigned char font_SUPERDIG[96][6];
extern const unsigned char font_tama_mini02[96][5];
extern const unsigned char font_zxpix[96][6];

// Font object declarations
extern Font font_5x5_obj;
extern Font font_7linedigital_obj;
extern Font font_acme_5_outlines_obj;
extern Font font_aztech_obj;
extern Font font_BMplain_obj;
extern Font font_BMSPA_obj;
extern Font font_Blokus_obj;
extern Font font_bubblesstandard_obj;
extern Font font_Commo_Monospaced_obj;
extern Font font_crackers_obj;
extern Font font_formplex12_obj;
extern Font font_haiku_obj;
extern Font font_HISKYF21_obj;
extern Font font_homespun_obj;
extern Font font_HUNTER_obj;
extern Font font_m38_obj;
extern Font font_Minimum_obj;
extern Font font_Minimum_1_obj;
extern Font font_pzim3x5_obj;
extern Font font_Raumsond_obj;
extern Font font_renew_obj;
extern Font font_sloth_obj;
extern Font font_SUPERDIG_obj;
extern Font font_tama_mini02_obj;
extern Font font_zxpix_obj;

class LowLevelRenderer {
private:
    uint8_t* bit_buffer;
    int V_WIDTH;
    int V_HEIGHT;
    const Font* current_font;
    bool clipping_enabled;
    int clip_x, clip_y, clip_width, clip_height;
    bool text_color;
    void draw_corner_arc(int center_x, int center_y, int radius, int quadrant, bool on);
    void fill_bottom_flat_triangle(int x1, int y1, int x2, int y2, int x3, int y3, bool on);
    void fill_top_flat_triangle(int x1, int y1, int x2, int y2, int x3, int y3, bool on);
    bool is_point_in_clip_rect(int x, int y);

public:
    LowLevelRenderer(uint8_t* buffer, int width, int height);

    // Font management
    void set_font(const Font* font);
    void set_text_color(bool color);
    Font get_current_font() const { return *current_font; }
    bool get_current_text_color() const { return text_color; }
    int get_width() const { return V_WIDTH; }
    int get_height() const { return V_HEIGHT; }

    // --- 1-BIT DRAWING PRIMITIVES ---
    void set_pixel(int x, int y, bool on);
    void draw_line(int x0, int y0, int x1, int y1, bool on, int width = 1);
    void draw_rectangle(int x, int y, int width, int height, bool on, int line_width);
    void draw_filled_rectangle(int x, int y, int width, int height, bool on, int line_width);
    void draw_rounded_rectangle(int x, int y, int width, int height, int radius, bool on, bool filled = false);
    void draw_triangle(int x1, int y1, int x2, int y2, int x3, int y3, bool on);
    void draw_filled_triangle(int x1, int y1, int x2, int y2, int x3, int y3, bool on);
    void draw_ellipse(int center_x, int center_y, int radius_x, int radius_y, bool on);
    void draw_filled_ellipse(int center_x, int center_y, int radius_x, int radius_y, bool on);
    void draw_polygon(const std::vector<std::pair<int, int>>& points, bool on);
    void draw_filled_polygon(const std::vector<std::pair<int, int>>& points, bool on);
    void draw_arc(int center_x, int center_y, int radius, int start_angle, int end_angle, bool on);
    
    // Bitmap drawing
    void draw_bitmap(const unsigned char* bitmap, int x, int y, int width, int height, bool invert = false);
    
    // Clipping functions
    void set_clip_rect(int x, int y, int width, int height);
    void reset_clip_rect();
    bool is_clipping_enabled() const;
    
    // Buffer operations
    void invert_buffer();
    void clear_buffer();
    
    void draw_circle(int x, int y, int radius, bool on);
    void draw_filled_circle(int x, int y, int radius, bool on);
    int draw_char_vcol(int x, int y, char c);
    void draw_string(int x, int y, const std::string &text, int spacing = 1);
    int draw_char_scaled(int x, int y, char c, int scale);
    int draw_string_scaled(int x, int y, const char* text, int scale, int spacing = 1);
};

#endif // LOW_LEVEL_RENDER_H