// bgfload.h - C++14 loader for VWE .BGF (DIV-BIZ2) geometry, adapted from the
// proven standalone port loader (port/src/bgf.cpp). Resolves the model under the
// pod content tree (VIDEO\ + VIDEO\GEO\...) and its .BMF material libraries +
// texture image basenames. Produces an L4VERTEX-compatible vertex/index/batch set
// ready to be turned into an ID3DXMesh by d3d_OBJECT.
//
// Self-contained: uses only the Win32 API for directory scanning (no <filesystem>,
// so it builds under the engine's C++14 target).
#pragma once
#include <cstdint>
#include <string>
#include <vector>

// Layout MUST match L4VERTEX (L4D3D.h): XYZ | NORMAL | DIFFUSE | TEX1.
struct BgfVtx {
    float x, y, z;
    float nx, ny, nz;
    uint32_t color;   // ARGB 0xAARRGGBB (unused once material diffuse drives lighting)
    float u, v;
};

// One draw range sharing a material.
struct BgfDrawBatch {
    uint32_t indexStart = 0;
    uint32_t indexCount = 0;
    uint32_t color = 0xFFB0B0B8u;  // ARGB fallback / resolved diffuse
    std::string texPath;           // resolved texture image file (.vtx/.bsl/.tga), or empty
    // BSL BIT-SLICE (BMF TEXTURE tag 0x18, absent = 0): which 4-bit slice of the
    // .bsl container this texture samples (0..5 mono; 7 = RGB444, 8 = RGBA4444).
    // BSLs pack up to SIX grayscale sub-images per file (mech skins: BLKHWK.BSL
    // holds blkhwk1..4); decoding the packed word as one RGBA image overlaid
    // 2-3 different sheets as color channels = the rainbow "graffiti" mechs.
    int texChannel = 0;
    // RAMP (task #20): colorize the grayscale texture by luminance across
    // rampLo->rampHi (the authentic IG-board terrain colouring).  When set, the
    // renderer bakes lerp(rampLo, rampHi, texLum) into the texture and draws with
    // a WHITE material so the ramp colour shows directly.
    bool  hasRamp = false;
    float rampLo[3] = {0,0,0};
    float rampHi[3] = {1,1,1};
    // EMISSIVE (tag 0x26): self-lit material colour.  Pure-emissive materials
    // (diffuse black + emissive set, e.g. btpolar:pintBIceEmit_mtl -- the polar
    // ice mounds) render as an UNLIT glow: tex x emissive, no sun/ambient.
    bool  hasEmissive = false;
    float emissive[3] = {0,0,0};
    // LOD band (the LOD chunk's 0x2046 header = [near..far) viewing range).  The
    // authentic renderer selects the LOD whose band contains the camera distance;
    // "take the first LOD" broke composite structures (arena buildings/ad signs)
    // whose NEAR band is a detail subset and whose massing lives in the FAR bands.
    float lodNear = 0.0f;
    float lodFar  = 1.0e9f;        // default: always drawn (single-LOD models)
    // PATCH-level SV_SPECIAL "PUNCH" (the 1995 L4VIDEO TestSpecialCallBack ->
    // dpl_Punchize): per-texel punch-through -- black texels are HOLES (cutout
    // lattice: arena scaffold layers AR01-04, gratings).  Drawn SOLID they
    // shingle near-coplanar over the massing = depth-shimmer "noisy surfaces".
    bool punch = false;
    // LAYER DEPTH BIAS (additive objects): the layers contain EXACTLY-COPLANAR
    // duplicated surfaces (flush wall patches between detail + massing).  The
    // IG board resolved those deterministically (exact per-polygon plane
    // equations -> identical depth -> submission order wins); D3D9 interpolates
    // per-vertex, so two tessellations of one plane differ by rounding per
    // pixel = venetian-blind z-fight stripes, at ANY distance.  Each finer
    // layer gets a slightly more negative normalized-depth bias so coplanar
    // overlaps always resolve to the detail layer.  0 = no bias (massing/
    // non-additive).
    float lodBias = 0.0f;
    // SHADOW MATERIAL (e.g. basev:shadow_mtl): baked ground-shadow quads
    // (MECHMOVS.BGF = two coplanar quads at y=0.1 under the wreck props).
    // Drawn opaque they z-fight each other/the floor; an all-shadow object is
    // routed through the mech-shadow pipeline (translucent dark, depth-biased,
    // no z-write) instead.
    bool shadowMat = false;
};

struct BgfData {
    std::vector<BgfVtx> verts;
    std::vector<uint32_t> indices;   // triangle list (already double-sided)
    std::vector<BgfDrawBatch> batches;
    bool ok = false;
    std::string error;
    int tris = 0;          // unique (single-sided) triangle count
    int matTotal = 0, matResolved = 0;
};

// Resolve `name` (e.g. "blx_cop.bgf", basename only) under the pod content tree and
// load it. Returns false (with .error set) if not found / no geometry.
bool LoadBgfFile(const std::string& name, BgfData& out);

// DAY/NIGHT path priority (task #20): the renderer (DPLReadEnvironment) passes the
// INI's objectpath/materialpath/texmappath search dirs, MOST-SPECIFIC-FIRST, so the
// loader picks the correct time-of-day variant of a colliding stem instead of
// first-match-wins.  cacheKey is "bgf" (objects), "bmf" (material libs), or "img"
// (textures).  Invalidates that index so it rebuilds with the new priority.
void SetVideoPathPriority(const std::string& cacheKey, const std::vector<std::string>& dirs);
