#pragma once
#include "VoxelTypes.h"
#include "VoxelWorld.h"

namespace voxel {

// ── Binary Greedy Mesher (CPU implementation, port of cgerikj) ──
// Generates PackedQuad list for a chunk using binary greedy meshing.
// For each axis, uses bitmask operations to find visible faces,
// then greedily merges same-material quads.
class VoxelMesher {
public:
    // Mesh a single chunk, populating chunk.quads
    // Returns number of quads generated
    static uint32_t meshChunk(Chunk& chunk, const VoxelWorld& world);

private:
    // Per-axis binary face culling
    // col_masks[axis][u][v] = 32-bit mask of solid voxels along axis
    struct AxisMasks {
        uint32_t solid[CHUNK_SIZE][CHUNK_SIZE]; // solid[u][v] = bitmask along axis
    };

    static void buildAxisMasks(const Chunk& chunk, AxisMasks masks[3]);

    // Greedy merge faces of same material into larger quads
    static void greedyMerge(
        const Chunk& chunk,
        const VoxelWorld& world,
        uint8_t face,
        const uint32_t faceMasks[CHUNK_SIZE][CHUNK_SIZE],
        std::vector<PackedQuad>& outQuads
    );

    // Calculate ambient occlusion for quad corners
    static uint8_t calcAO(const VoxelWorld& world, const ChunkPos& cpos,
                          int x, int y, int z, uint8_t face);
};

// ── Naive Surface Nets Mesher (Phase 5) ─────────────────────────
// Generates smooth triangle mesh for voxels marked FLAG_SMOOTH.
// Algorithm: one vertex per surface cell, positioned at edge-crossing centroid.
// Quads emitted for each edge with sign change, then split into 2 triangles.
class SmoothMesher {
public:
    // Mesh smooth voxels in a chunk, populating chunk.smoothVertices.
    // Returns number of smooth vertices generated (always multiple of 3, triangle list).
    static uint32_t meshChunk(Chunk& chunk, const VoxelWorld& world);

private:
    // SDF value at a voxel position (solid smooth = -1, empty = +1)
    // Non-smooth solid voxels are treated as walls (SDF = -1 at boundary)
    static float computeSDF(const Chunk& chunk, const VoxelWorld& world,
                            int x, int y, int z);

    // Compute SDF gradient (numerical central differences) for normal
    static void computeNormal(const Chunk& chunk, const VoxelWorld& world,
                              int x, int y, int z, float& nx, float& ny, float& nz);
};

} // namespace voxel
