#ifndef AI_WIRE_H
#define AI_WIRE_H

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

#define AIW_MAX_CHANNELS 122u
#define AIW_HEADER_BYTES 8u
#define AIW_TICKET_PAYLOAD_BYTES 26u
#define AIW_RESULT_FIXED_PAYLOAD_BYTES 35u
#define AIW_CRC_BYTES 2u
#define AIW_MAX_PACKET_BYTES (AIW_HEADER_BYTES + AIW_RESULT_FIXED_PAYLOAD_BYTES + AIW_MAX_CHANNELS + AIW_CRC_BYTES)
#define AIW_RESULT_FLAG_HAND_PRESENT 0x01u
#define AIW_RESULT_ALLOWED_FLAGS AIW_RESULT_FLAG_HAND_PRESENT

typedef struct {
    uint64_t session_id;
    uint32_t ticket_id;
    uint32_t calibration_id;
    uint16_t channels;
    uint64_t min_source_frame_seq;
} aiw_ticket;

typedef struct {
    uint64_t session_id;
    uint32_t ticket_id;
    uint32_t calibration_id;
    uint16_t channels;
    uint64_t capture_baseline_seq;
    uint64_t source_frame_seq;
    uint8_t status_flags;
    uint8_t pwm[AIW_MAX_CHANNELS];
} aiw_result;

/* Version-2 AI_REQUEST and AI_RESULT wire formats: NLAI magic, version/type, payload length,
   LE session/ticket/calibration/channel/frame fields, PWM bytes, CRC-16/CCITT-FALSE.
   AI_RESULT inserts status_flags after source_frame_seq. Hand-absent results must carry
   an all-zero PWM vector. This serializer does not establish UART timing or prove a new capture. */
bool aiw_encode_ticket(const aiw_ticket *ticket, uint8_t *out, size_t capacity,
                       size_t *written);
bool aiw_decode_ticket(const uint8_t *packet, size_t length, aiw_ticket *out);
bool aiw_encode_result(const aiw_result *result, uint8_t *out, size_t capacity,
                       size_t *written);
bool aiw_decode_result(const uint8_t *packet, size_t length, aiw_result *out);
uint16_t aiw_crc16_ccitt_false(const uint8_t *data, size_t length);

#endif
