#include "mesh_builder.h"

static void addFace(
    std::vector<Vertex>& vertices,
    std::vector<uint32_t>& indices,
    float x, float y, float z,
    int face
) {
    uint32_t start = static_cast<uint32_t>(vertices.size());

    float size = 1.0f;

    // 6 граней
    // 0 = +X, 1 = -X, 2 = +Y, 3 = -Y, 4 = +Z, 5 = -Z

    float verts[6][4][3] = {
        // +X
        {{x+size,y,z},{x+size,y+size,z},{x+size,y+size,z+size},{x+size,y,z+size}},
        // -X
        {{x,y,z},{x,y,z+size},{x,y+size,z+size},{x,y+size,z}},
        // +Y
        {{x,y+size,z},{x,y+size,z+size},{x+size,y+size,z+size},{x+size,y+size,z}},
        // -Y
        {{x,y,z},{x+size,y,z},{x+size,y,z+size},{x,y,z+size}},
        // +Z
        {{x,y,z+size},{x+size,y,z+size},{x+size,y+size,z+size},{x,y+size,z+size}},
        // -Z
        {{x,y,z},{x,y+size,z},{x+size,y+size,z},{x+size,y,z}}
    };

    for (int i = 0; i < 4; i++) {
        vertices.push_back({
            {verts[face][i][0], verts[face][i][1], verts[face][i][2]},
            {0.7f, 0.9f, 0.7f}
        });
    }

    indices.insert(indices.end(), {
        start, start+1, start+2,
        start, start+2, start+3
    });
}

MeshData MeshBuilder::build(const World& world) {
    MeshData mesh;

    auto blocks = world.collectSolidBlocks();

    auto isSolidAt = [&](int x, int y, int z) {
        for (auto& b : blocks) {
            if (b.worldX == x && b.worldY == y && b.worldZ == z) {
                return true;
            }
        }
        return false;
    };

    for (auto& b : blocks) {
        int x = b.worldX;
        int y = b.worldY;
        int z = b.worldZ;

        if (!isSolidAt(x+1,y,z)) addFace(mesh.vertices, mesh.indices,x,y,z,0);
        if (!isSolidAt(x-1,y,z)) addFace(mesh.vertices, mesh.indices,x,y,z,1);
        if (!isSolidAt(x,y+1,z)) addFace(mesh.vertices, mesh.indices,x,y,z,2);
        if (!isSolidAt(x,y-1,z)) addFace(mesh.vertices, mesh.indices,x,y,z,3);
        if (!isSolidAt(x,y,z+1)) addFace(mesh.vertices, mesh.indices,x,y,z,4);
        if (!isSolidAt(x,y,z-1)) addFace(mesh.vertices, mesh.indices,x,y,z,5);
    }

    return mesh;
}