#pragma once

#include <stdint.h>
#include <stdbool.h>


#ifdef __cplusplus
extern "C" {
#endif


/* ============================================================
   === Конфигурация времени компиляции
   ============================================================ */

/*
 * Максимальное количество буферов,
 * доступное в данной сборке.
 *
 * RP2040: обычно 1
 * RP2350: можно 2
 */
#ifndef DISPLAY_MAX_BUFFERS
#define DISPLAY_MAX_BUFFERS 2
#endif


/* ============================================================
   === Режимы
   ============================================================ */

typedef enum
{
    /* Безопасный режим: движок сам управляет сменой буферов. */
    DISPLAY_MODE_SAFE = 0,

    /* Ручной режим: приложению нужно управлять буферами самостоятельно. */
    DISPLAY_MODE_RAW

} display_mode_t; /* Тип режима работы подсистемы дисплея. */


/* ============================================================
   === Конфигурация
   ============================================================ */

typedef struct
{
    uint16_t width;  /* Ширина кадра в пикселях. */
    uint16_t height; /* Высота кадра в пикселях. */

    /*
     * 1 или 2.
     * Должно быть <= DISPLAY_MAX_BUFFERS.
     */
    uint8_t buffer_count; /* Количество используемых кадровых буферов. */

    display_mode_t mode; /* Выбранный режим работы буферизации. */

} display_config_t; /* Параметры инициализации подсистемы дисплея. */


/* ============================================================
   === Жизненный цикл
   ============================================================ */

/* Инициализирует подсистему дисплея и выделяет нужные ресурсы. */
void display_init(const display_config_t* cfg);


/* ============================================================
   === Новый paint-контракт
   ============================================================ */

/* Неблокирующе начинает рисование кадра и возвращает буфер, либо NULL. */
uint16_t* display_begin_paint_try(void);

/* Блокирующе начинает рисование кадра и возвращает валидный буфер. */
uint16_t* display_begin_paint_blocking(void);

/* Завершает рисование кадра и передаёт его в вывод (в SAFE+2 возможна отложенная отправка). */
/* false при ошибке контракта или переполнении очереди из одного pending-кадра. */
bool display_end_paint(void);


/* Возвращает буфер, который в данный момент отправляется через DMA. */
uint16_t* display_get_scanout_buffer(void);


/* ============================================================
   === Управление буферами (только режим RAW)
   ============================================================ */

/* Меняет местами draw/scanout буферы; false при недопустимых условиях. */
bool display_swap_buffers(void);


/* ============================================================
   === Управление кадром
   ============================================================ */

/* Запускает DMA-передачу текущего scanout-буфера. */
/* В SAFE+2 при занятом DMA ставит кадр в очередь из одного pending-кадра. */
bool display_submit(void);


/* Возвращает true, когда DMA неактивен и нет отложенного pending-кадра. */
bool display_ready(void);


/* Блокирует выполнение до полного завершения текущей DMA-передачи. */
void display_wait(void);


/* ============================================================
   === Хук IRQ
   ============================================================ */

/* Вызывается из реального DMA IRQ-обработчика для уведомления движка. */
void display_dma_irq_handler(void);


#ifdef __cplusplus
}
#endif
