#pragma once

#include <stdint.h>

#include "crArray.h"

// every value needs a generator below — crBatchedPrimitives asserts on boot that each one built geometry
enum class EPrimitive : uint8_t
{
    BOX = 0,
    SPHERE,
    SPHERE_SHELL, // sphere plus an inward-facing copy — the pass culls backfaces, so this is the only
                  // one that survives the camera being inside it (containment fields, domes)
    OCTAHEDRON,   // unit octahedron (vertices on the axes) — reads as a crystal / dart
    RING,         // flat two-sided annulus in the XY plane (outer radius 1) — planet rings, discs
    RING_THIN,    // same, narrow band — shockwave fronts that stay slim while scaling
    ICOSAHEDRON,  // unit icosahedron, hard faceted — asteroids, elite hulls
    BEAM,         // unit box subdivided along X — dense verts so vertex-warping materials read clearly
    TETRAHEDRON,  // unit tetrahedron, hard faceted — triangle silhouette from almost any angle

    // gem chips — an outline in the XY plane cut like a stone: sloped crown facets to an apex
    // (z +1), rim at 0, flat bottom at -1 (scale.z = half-height). face-up under a top-down camera
    // they hold a constant, maximal silhouette, and the crown keeps light moving across the faces
    // while they yaw; a directional chip's identity axis is authored toward +X so the standard
    // nose-along-flight rotation (CosSin about Z) aims it
    ARROW,        // isosceles arrowhead pointing +X — heading-aligned chasers
    HEXAGON,      // regular hex plate — blockers, armor
    STAR,         // four-point star, the +X point elongated — a hunter with a visible lead spike

    // pentagonal pyramid, apex +X, base ring in YZ. the one shape here that can ROLL about its own
    // heading without losing its read: projected top-down, a 5-gon base spans 1.81..1.90 r as it
    // turns, so the outline stays a triangle within 5% while every facet cycles through the light.
    // (a 4-gon base would breathe 41%, a flat chip would go edge-on and vanish)
    SPIKE,
    // the same 5-gon ring closed by a second apex at -X — a kite, and roll-invariant for the same
    // reason SPIKE is. an octahedron would read as the same silhouette but its ring is a 4-gon,
    // which breathes 41% under roll against this one's 5%
    DIAMOND,

    _SIZE
};

// output contract: interleaved pos3 + normal3, CCW seen from outside, unit extent (the instance
// scale carries the real size), uint16 indices. crBatchedPrimitives owns the GL upload
struct crPrimitiveGeometry
{
    // tessellation this build is authored for — edited per game.
    // BEAM is subdivided so a vertex shader has something to bend: lowering it removes
    // deformation range, not just triangles
    // SPHERE is the one spawned in bulk (starfields, props) and stays cheap; SPHERE_SHELL is
    // arena-scale, where the silhouette IS the shape, and affords far more only because it is a
    // handful of instances. separate counts so neither drags the other's cost
    static constexpr int32_t SPHERE_SEGMENTS = 24;
    static constexpr int32_t SPHERE_RINGS    = 14;
    static constexpr int32_t SHELL_SEGMENTS  = 96;
    static constexpr int32_t SHELL_RINGS     = 48;
    static constexpr int32_t RING_SEGMENTS   = 128;
    static constexpr float   RING_INNER      = 0.55f;   // inner radius of the unit annulus
    static constexpr float   RING_INNER_THIN = 0.99f;   // RING_THIN variant — hairline band (0.01 x radius)
    static constexpr int32_t BEAM_SEGMENTS   = 32;      // X subdivisions of the BEAM box

    static void BuildBox        ( crArray<float>* verts, crArray<uint16_t>* indices );
    static void BuildSphere     ( crArray<float>* verts, crArray<uint16_t>* indices );
    static void BuildSphereShell( crArray<float>* verts, crArray<uint16_t>* indices );   // BuildSphere + a wound-inward, normal-flipped copy
    static void BuildOctahedron ( crArray<float>* verts, crArray<uint16_t>* indices );
    static void BuildIcosahedron( crArray<float>* verts, crArray<uint16_t>* indices );
    static void BuildBeam       ( crArray<float>* verts, crArray<uint16_t>* indices );
    static void BuildRing       ( crArray<float>* verts, crArray<uint16_t>* indices, float inner );
    static void BuildTetrahedron( crArray<float>* verts, crArray<uint16_t>* indices );
    static void BuildArrow      ( crArray<float>* verts, crArray<uint16_t>* indices );
    static void BuildHexagon    ( crArray<float>* verts, crArray<uint16_t>* indices );
    static void BuildStar       ( crArray<float>* verts, crArray<uint16_t>* indices );
    static void BuildSpike      ( crArray<float>* verts, crArray<uint16_t>* indices );
    static void BuildDiamond    ( crArray<float>* verts, crArray<uint16_t>* indices );
};
