#include "low_level_display_st7796.h"
#include <stdio.h>
#include <stdlib.h>

// RGB565 color definitions
#define COLOR_BLACK   0x0000
#define COLOR_WHITE   0xFFFF

LowLevelDisplayST7796::LowLevelDisplayST7796(const st7796_config* cfg, int w, int h, bool invert)
    : config(cfg), width(w), height(h), initialized(false), rgb_buffer(nullptr), invert_color(invert) {
}

LowLevelDisplayST7796::~LowLevelDisplayST7796() {
    if (rgb_buffer) {
        free(rgb_buffer);
        rgb_buffer = nullptr;
    }
}

bool LowLevelDisplayST7796::init() {
    if (initialized) {
        return true;
    }
    
    st7796_init(config, width, height);
    
    // Allocate RGB565 buffer once (reused for all draw operations)
    size_t buffer_size = width * height * sizeof(uint16_t);
    rgb_buffer = (uint16_t *)malloc(buffer_size);
    if (!rgb_buffer) {
        printf("Error: Failed to allocate %zu bytes for RGB buffer\n", buffer_size);
        return false;
    }
    printf("ST7796 display initialized: %dx%d (RGB buffer: %zu bytes)\n", width, height, buffer_size);
    
    initialized = true;
    return true;
}

void LowLevelDisplayST7796::clear(bool white) {
    bool out_white = invert_color ? !white : white;
    st7796_fill(out_white ? COLOR_WHITE : COLOR_BLACK);
}

void LowLevelDisplayST7796::draw_pixel(int x, int y, bool white) {
    bool out_white = invert_color ? !white : white;
    st7796_draw_pixel(x, y, out_white ? COLOR_WHITE : COLOR_BLACK);
}

void LowLevelDisplayST7796::draw_buffer(const uint8_t* bit_buffer) {
    if (!bit_buffer || !rgb_buffer) return;
    // Convert 1-bit buffer to RGB565 using persistent buffer
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            int byte_index = (y * width + x) / 8;
            int bit_index = 7 - (x % 8);
            bool pixel_white = (bit_buffer[byte_index] >> bit_index) & 0x01;
            bool out_white = invert_color ? !pixel_white : pixel_white;
            rgb_buffer[y * width + x] = out_white ? COLOR_WHITE : COLOR_BLACK;
        }
    }
    // Draw entire buffer at once
    st7796_set_cursor(0, 0);
    st7796_write(rgb_buffer, width * height);
}

void LowLevelDisplayST7796::refresh() {
    // ST7796 updates immediately, no refresh needed
}

void LowLevelDisplayST7796::set_backlight(bool on) {
    // ST7796 driver doesn't have backlight control yet
    // TODO: Add GPIO control for backlight pin
    (void)on;
}

void LowLevelDisplayST7796::set_rotation(uint8_t rotation) {
    // ST7796 driver doesn't have rotation control yet
    // TODO: Add MADCTL register manipulation for rotation
    (void)rotation;
}
