#pragma once
// repo: pictureFrame-firmware
//
// Hardware specifics (panel dimensions + GPIO pinout) come from the build
// env's -D flags in platformio.ini, not from this file. That keeps the
// shared sources panel-agnostic and lets each `src/panels/{vendor}/v{N}/`
// subtree stay focused on its own driver.
//
// Strict: missing a -D flag is a compile error here, not a silent fallback
// to V1 values. A bad env config fails fast at build time. Native tests
// (UNIT_TEST defined) get harmless defaults — they don't drive real
// hardware, so the values never matter beyond satisfying the compiler.

// ── EPD pixel dimensions ─────────────────────────────────────────────────
#ifndef EPD_WIDTH
#  ifdef UNIT_TEST
#    define EPD_WIDTH 800
#  else
#    error "EPD_WIDTH not defined — set -DEPD_WIDTH=… in platformio.ini build_flags"
#  endif
#endif
#ifndef EPD_HEIGHT
#  ifdef UNIT_TEST
#    define EPD_HEIGHT 480
#  else
#    error "EPD_HEIGHT not defined — set -DEPD_HEIGHT=… in platformio.ini build_flags"
#  endif
#endif

// Largest panel width any build env may target. Static buffers in the
// driver use this to size themselves at compile time so we don't pay for
// heap allocation on every draw. Default: assume the active env's panel
// (so V1 builds get an 800-wide buffer; V2 builds will set it to 1872).
#ifndef MAX_PANEL_WIDTH
#define MAX_PANEL_WIDTH EPD_WIDTH
#endif

// ── GPIO pinout ──────────────────────────────────────────────────────────
// Same UNIT_TEST escape: native tests get the V1 dev-board pinout so
// shared sources compile, even though no real GPIO is touched.
#ifndef PIN_SCK
#  ifdef UNIT_TEST
#    define PIN_SCK 18
#  else
#    error "PIN_SCK not defined — set -DPIN_SCK=… in platformio.ini build_flags"
#  endif
#endif
#ifndef PIN_MOSI
#  ifdef UNIT_TEST
#    define PIN_MOSI 23
#  else
#    error "PIN_MOSI not defined — set -DPIN_MOSI=… in platformio.ini build_flags"
#  endif
#endif
#ifndef PIN_CS
#  ifdef UNIT_TEST
#    define PIN_CS 5
#  else
#    error "PIN_CS not defined — set -DPIN_CS=… in platformio.ini build_flags"
#  endif
#endif
#ifndef PIN_DC
#  ifdef UNIT_TEST
#    define PIN_DC 17
#  else
#    error "PIN_DC not defined — set -DPIN_DC=… in platformio.ini build_flags"
#  endif
#endif
#ifndef PIN_RST
#  ifdef UNIT_TEST
#    define PIN_RST 16
#  else
#    error "PIN_RST not defined — set -DPIN_RST=… in platformio.ini build_flags"
#  endif
#endif
#ifndef PIN_BUSY
#  ifdef UNIT_TEST
#    define PIN_BUSY 4
#  else
#    error "PIN_BUSY not defined — set -DPIN_BUSY=… in platformio.ini build_flags"
#  endif
#endif

// ── Panel telemetry strings ──────────────────────────────────────────────
// Reported to the server at provisioning. PANEL_ID identifies the hardware
// model (vendor + size); PANEL_FW_VERSION lives in src/panels/{…}/v{N}/version.h
// and ticks when the panel-specific driver code changes.
#ifndef PANEL_ID
#define PANEL_ID "unknown"
#endif

// ── Reset button (BOOT button = GPIO 0 on most dev boards) ──────────────
#define PIN_BTN_RESET  0
#define RESET_HOLD_MS  5000

// ── EPD color nibbles ────────────────────────────────────────────────────
// Verified on Waveshare 7.3" hardware. Same map on 13.3" Spectra 6.
#define COLOR_BLACK   0x0
#define COLOR_WHITE   0x1
#define COLOR_YELLOW  0x2
#define COLOR_RED     0x3
#define COLOR_BLUE    0x5
#define COLOR_GREEN   0x6

// ── NVS ──────────────────────────────────────────────────────────────────
#define NVS_NAMESPACE  "pf"
#define NVS_KEY_SSID        "ssid"
#define NVS_KEY_PASS        "pass"
#define NVS_KEY_IMG_ID      "img_id"
#define NVS_KEY_DRAW_NEEDED "draw"
#define NVS_KEY_ERR_BORDER  "err"     // set when display is showing a sync-fail border; force a clean redraw on next 200/304
#define NVS_KEY_SCHEMA_V    "schema_v"
// Set on every fresh provisioning (WiFi-setup completion). Stays in NVS across
// reboots until the server explicitly acknowledges the device is claimed by
// returning X-Claimed: 1 — at which point the firmware clears the flag and
// resumes regular operation. Without this, a device that gets sold and reset
// would silently keep displaying the prior owner's photos until the new
// owner happens to navigate to /setup/{mac}.
#define NVS_KEY_JUST_PROVISIONED "just_prov"

// Bump when introducing a schema migration. Each new value can force a one-shot
// recovery action on first boot of the new firmware.
#define NVS_SCHEMA_VERSION  1

// Width of the sync-fail / no-WiFi border, in pixels.
#define BORDER_THICKNESS_PX 4

// ── Network ──────────────────────────────────────────────────────────────
#define APP_BASE_URL      "https://wevisto.com"
#define AP_IP             "192.168.4.1"
// AP security — WPA2-PSK with a fixed password baked into both the
// firmware and the WIFI: QR. Open networks have flakier iOS captive-
// portal behavior (esp. on lock-screen-camera join paths); a secured
// network is the pattern aqua-iq uses successfully on the same iOS
// versions. The password is embedded in the QR so the user never types
// it — there's no real secret value.
#define AP_PASSWORD       "pictureframe"
#define AP_CHANNEL        6
#define AP_SETTLE_MS      1500
#define WIFI_TIMEOUT_MS   30000
// Server's X-Interval-Ms is the primary schedule — driven by the user's
// rotationIntervalMinutes / wakeTimes settings. The constants below are
// only safety nets:
//   - FALLBACK is used when the server omits the header (shouldn't happen
//     in normal operation, but guards against a rolling deploy or hand-
//     crafted response).
//   - CLAMP_MIN/MAX bound the server value to sane physical limits — no
//     runaway polling on a malformed 0/negative, no week-long naps on a
//     misconfigured 999 days. CLAMP_MAX is just past 24 h to give DST
//     transitions and edge-case wake-time math a little slack.
#ifndef FETCH_INTERVAL_MS_FALLBACK
#define FETCH_INTERVAL_MS_FALLBACK 60000ULL          // 1 min, used only when no X-Interval-Ms header
#endif
#ifndef SLEEP_CLAMP_MIN_MS
#define SLEEP_CLAMP_MIN_MS         30000ULL          // 30 s — protect against runaway polls
#endif
#ifndef SLEEP_CLAMP_MAX_MS
#define SLEEP_CLAMP_MAX_MS         (25ULL * 60ULL * 60ULL * 1000ULL)  // 25 h — past 24h with DST slack
#endif
// Until the device receives its first image (img_id still -1), poll fast
// so the user's first photo lands within ~15 s of finishing setup —
// regardless of what schedule the server's X-Interval-Ms encodes. Bypasses
// SLEEP_CLAMP_MIN_MS because that's about runaway protection in the
// steady state; the bootstrap window is bounded by "first image arrives."
#ifndef FIRST_IMAGE_POLL_INTERVAL_MS
#define FIRST_IMAGE_POLL_INTERVAL_MS 15000ULL
#endif
// During bootstrap (no image yet) the device stays awake and polls in a
// tight loop — keeping WiFi up between requests so the user doesn't wait
// through a ~5 s deep-sleep + reconnect on every retry. Once the first
// image arrives the device enters the normal scheduled deep sleep.
#ifndef BOOTSTRAP_RETRY_INTERVAL_MS
#define BOOTSTRAP_RETRY_INTERVAL_MS 2000ULL
#endif
#define IMAGE_PATH        "/img.bin"
