#ifndef W3CS_RAIN_QUAD_H
#define W3CS_RAIN_QUAD_H

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

#ifdef __cplusplus
extern "C" {
#endif

/* Opcode 42 is deliberately narrow. It only represents Warcraft III's
 * observed rain billboard layout. Any different vertex, attribute, order,
 * or size must use an older blob opcode. */
#define W3CS_RAIN_QUAD_MARKER 0x5251u
#define W3CS_RAIN_QUAD_VERSION 1u
#define W3CS_RAIN_QUAD_STRIDE 36u
#define W3CS_RAIN_QUAD_VERTICES 4u
#define W3CS_RAIN_QUAD_BYTES 144u
#define W3CS_RAIN_QUAD_LANES 9u
#define W3CS_RAIN_QUAD_BODY_HEADER_SIZE 16u
#define W3CS_RAIN_QUAD_MAX_WIDTH 16u

/* D3D row-vector convention: [x y z 1] * object_to_clip. */
struct w3cs_rain_quad_projection {
    float object_to_clip[16];
    float viewport_x;
    float viewport_y;
    float viewport_width;
    float viewport_height;
};

struct w3cs_rain_quad_result {
    uint8_t position_drop_bits;
    float maximum_xy_error_px;
    float maximum_depth_error_px;
    float maximum_combined_error_px;
    uint32_t quad_count;
};

/* Encode the opcode-42 body, excluding the standard 24-byte blob identity.
 *
 * The input must be FVF 0x152 vertices with stride 36 and the exact observed
 * rain template. Each four-vertex group must be ordered by UV as 00, 01,
 * 10, 11. The encoder tries max_drop_bits down through zero and accepts only
 * a reconstruction that:
 *   - stays within maximum_combined_error_px for screen XY plus scaled depth;
 *   - keeps all six homogeneous clip-plane classifications identical;
 *   - keeps source and candidate depth inside D3D's 0 <= z <= w volume; and
 *   - reconstructs every non-position attribute exactly.
 *
 * Pass body=NULL to query the largest required capacity. This query validates
 * only sizes, not vertex content or projection. On a normal call, body_size
 * receives the exact encoded size and reconstructed receives the exact bytes
 * that the browser will hash and store. No partial output is committed on
 * failure. */
bool w3cs_rain_quad_encode_body(
    const uint8_t *vertices,
    uint32_t vertex_bytes,
    const struct w3cs_rain_quad_projection *projection,
    float maximum_combined_error_px,
    unsigned max_drop_bits,
    uint8_t *body,
    size_t body_capacity,
    size_t *body_size,
    uint8_t *reconstructed,
    size_t reconstructed_capacity,
    struct w3cs_rain_quad_result *result);

/* Decode one complete canonical body. The decoder rejects redundant widths,
 * nonzero padding, trailing data, unknown versions, and invalid blob sizes.
 * The output is unchanged on failure. */
bool w3cs_rain_quad_decode_body(
    const uint8_t *body,
    size_t body_size,
    uint32_t vertex_bytes,
    uint8_t *vertices,
    size_t vertex_capacity,
    unsigned *position_drop_bits);

/* Exact upper bound for a body of vertex_bytes. Zero means invalid size. */
size_t w3cs_rain_quad_body_capacity(uint32_t vertex_bytes);

#ifdef __cplusplus
}
#endif

#endif
