/**
 * DreamStack Bitstream Protocol — C port for ESP32-P4
 *
 * Ported from engine/ds-stream/src/protocol.rs
 * Header format and frame types for the thin client.
 */

#pragma once
#include <stdint.h>

// ─── Magic bytes ───
#define DS_MAGIC_0  0xD5
#define DS_MAGIC_1  0x7A

// ─── Header size ───
#define DS_HEADER_SIZE  16

// ─── Frame types (output: source → receiver) ───
#define DS_FRAME_PIXELS          0x01  // Raw RGBA pixel data
#define DS_FRAME_COMPRESSED      0x02  // PNG/WebP compressed
#define DS_FRAME_DELTA           0x03  // XOR delta from previous
#define DS_FRAME_SIGNAL_SYNC     0x10  // Full signal state (JSON)
#define DS_FRAME_SIGNAL_DIFF     0x11  // Changed signals (JSON)
#define DS_FRAME_SCHEMA          0x12  // Schema announcement
#define DS_FRAME_KEYFRAME        0xF0  // Reset state
#define DS_FRAME_PING            0xFE  // Heartbeat
#define DS_FRAME_END             0xFF  // Stream end

// ─── Input types (receiver → source) ───
#define DS_INPUT_POINTER         0x01
#define DS_INPUT_KEY             0x02
#define DS_INPUT_SCROLL          0x03
#define DS_INPUT_TOUCH           0x04
#define DS_INPUT_GAMEPAD_AXIS    0x10
#define DS_INPUT_GAMEPAD_BTN     0x11
#define DS_INPUT_TEXT            0x20

// ─── Flags ───
#define DS_FLAG_INPUT            0x01
#define DS_FLAG_KEYFRAME         0x02
#define DS_FLAG_COMPRESSED       0x04

// ─── Frame header (16 bytes, little-endian) ───
typedef struct __attribute__((packed)) {
    uint8_t  magic[2];       // DS_MAGIC_0, DS_MAGIC_1
    uint8_t  frame_type;     // DS_FRAME_* or DS_INPUT_*
    uint8_t  flags;          // DS_FLAG_*
    uint16_t seq;            // Sequence number
    uint32_t timestamp;      // Milliseconds
    uint16_t width;          // Frame width (pixels)
    uint16_t height;         // Frame height (pixels)
    uint16_t payload_len;    // Following payload length
} ds_header_t;

// ─── Touch event (6 bytes) ───
typedef struct __attribute__((packed)) {
    uint8_t  id;             // Touch identifier (multi-touch)
    uint16_t x;              // X coordinate
    uint16_t y;              // Y coordinate
    uint8_t  phase;          // 0=start/move, 1=end, 2=cancel
} ds_touch_event_t;

/**
 * Parse a header from raw bytes.
 * Returns 0 on success, -1 if magic doesn't match.
 */
static inline int ds_parse_header(const uint8_t *buf, ds_header_t *hdr) {
    if (buf[0] != DS_MAGIC_0 || buf[1] != DS_MAGIC_1) return -1;
    *hdr = *(const ds_header_t *)buf;
    return 0;
}

/**
 * Encode a touch input message into a buffer.
 * Buffer must be at least DS_HEADER_SIZE + sizeof(ds_touch_event_t) = 22 bytes.
 * Returns total message size.
 */
static inline size_t ds_encode_touch(uint8_t *buf, uint16_t seq,
                                     uint32_t timestamp,
                                     const ds_touch_event_t *touch) {
    ds_header_t *hdr = (ds_header_t *)buf;
    hdr->magic[0] = DS_MAGIC_0;
    hdr->magic[1] = DS_MAGIC_1;
    hdr->frame_type = DS_INPUT_TOUCH;
    hdr->flags = DS_FLAG_INPUT;
    hdr->seq = seq;
    hdr->timestamp = timestamp;
    hdr->width = 0;
    hdr->height = 0;
    hdr->payload_len = sizeof(ds_touch_event_t);

    *(ds_touch_event_t *)(buf + DS_HEADER_SIZE) = *touch;
    return DS_HEADER_SIZE + sizeof(ds_touch_event_t);
}
