// qr_puzzle.h — camera-based QR sequence puzzle for the OV3660 on the
// Freenove ESP32-S3 Media Kit.  Uses esp32-camera (QVGA grayscale) + quirc.
//
// qr_puzzle_start: initialise the camera, spawn the scan task, and register
//   the sequence to match.  Returns ESP_ERR_INVALID_STATE if already running.
//   NOTE: after qr_puzzle_stop() the scan task deinits the camera
//   asynchronously — qr_puzzle_start returns ESP_ERR_INVALID_STATE until
//   teardown completes; callers should retry after a short delay (e.g. 100 ms).
// qr_puzzle_stop: request shutdown; the camera is deinitialized by the task
//   itself before it exits (frees PSRAM and powers down the sensor).
//
// CALLBACK SAFETY: the solved callback runs in the scan task context and MUST
//   NOT call qr_puzzle_start/qr_puzzle_stop directly — defer re-arming to
//   another task (e.g. via task notification or event group).
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "esp_err.h"

typedef void (*qr_solved_cb_t)(void);

// Optional frame-mirror hook (e.g. live viewfinder on the local display).
// Called from the scan task for every captured frame BEFORE decode, with the
// raw grayscale QVGA buffer. The callee must COPY the data and return fast
// (it blocks scanning); it runs in the scan task context — same restrictions
// as the solved callback. Pass NULL to disable. Survives start/stop cycles.
typedef void (*qr_preview_cb_t)(const uint8_t *gray, int width, int height);
void qr_puzzle_set_preview_cb(qr_preview_cb_t cb);

esp_err_t qr_puzzle_start(const char *const *expected, size_t count, qr_solved_cb_t cb);
void      qr_puzzle_stop(void);
// True while the scan task exists, including the async teardown window after stop.
bool      qr_puzzle_is_running(void);
