import { UintArrayForCount } from "../../../../core/collection/array/typed/uint_array_for_count.js";
import { geometry_compute_vertex_normals_indexed } from "./geometry_compute_vertex_normals_indexed.js";

/**
 *
 * @param {Sampler2D} samplerHeight
 * @param {Vector2} position
 * @param {Vector2} size
 * @param {Vector2} scale
 * @param {Vector2} totalSize
 * @param {number} resolution
 * @returns {{indices, vertices: Float32Array, normals: Float32Array, uvs: Float32Array}}
 */
export function build_height_field_geometry(samplerHeight, position, size, scale, totalSize, resolution) {

    const width = size.x;
    const height = size.y;


    const gridX1 = width * resolution;
    const gridY1 = height * resolution;

    const gridX2 = gridX1 - 1;
    const gridY2 = gridY1 - 1;

    let offset = 0, offset2 = 0;

    const vertexCount = gridX1 * gridY1;


    const vertices = new Float32Array(vertexCount * 3);

    const normals = new Float32Array(vertexCount * 3);

    const uvs = new Float32Array(vertexCount * 2);

    let y, x;

    const vMultiplier = (size.y / totalSize.y) / gridY2;
    const uMultiplier = (size.x / totalSize.x) / gridX2;

    const vConst = position.y / totalSize.y;
    const uConst = position.x / totalSize.x;

    const totalScaledSizeX = totalSize.x * scale.x;
    const totalScaledSizeY = totalSize.y * scale.y;

    //fill vertices
    let px, py, pz;
    for (y = 0; y < gridY1; y++) {

        const v = y * vMultiplier + vConst;

        pz = v * totalScaledSizeY;

        for (x = 0; x < gridX1; x++) {

            const u = x * uMultiplier + uConst;

            //get height sample
            const val = samplerHeight.sampleChannelBicubicUV(u, v, 0);

            px = u * totalScaledSizeX;
            py = val;

            vertices[offset] = px;
            vertices[offset + 1] = py;
            vertices[offset + 2] = pz;

            uvs[offset2] = u;
            uvs[offset2 + 1] = v;

            offset += 3;
            offset2 += 2;
        }
    }

    offset = 0;

    const IndexArray = UintArrayForCount(vertices.length / 3);

    /**
     * @type {Uint8Array|Uint16Array|Uint32Array}
     */
    const indices = new IndexArray(gridX2 * gridY2 * 6);

    //add faces
    //TODO TraingleStip mode is more efficient in terms of memory usage and probably GPU-time
    for (y = 0; y < gridY2; y++) {

        for (x = 0; x < gridX2; x++) {
            const a = x + gridX1 * y;
            const b = x + gridX1 * (y + 1);
            const c = (x + 1) + gridX1 * (y + 1);
            const d = (x + 1) + gridX1 * y;

            indices[offset] = a;
            indices[offset + 1] = b;
            indices[offset + 2] = d;

            indices[offset + 3] = b;
            indices[offset + 4] = c;
            indices[offset + 5] = d;

            offset += 6;
        }
    }

    geometry_compute_vertex_normals_indexed(vertices, normals, indices);

    //CleanupGeometry(geometry);
    return {
        indices: indices,
        vertices: vertices,
        normals: normals,
        uvs: uvs
    };
}