import { array_copy } from "../../../../../core/collection/array/array_copy.js";
import { Ray3 } from "../../../../../core/geom/3d/ray/Ray3.js";
import { sh3_basis_at } from "../../../../../core/geom/3d/sphere/harmonics/sh3_basis_at.js";
import { sh3_vector_accumulate } from "../../../../../core/geom/3d/sphere/harmonics/sh3_vector_accumulate.js";
import { vector_scale_array } from "../../../../../core/geom/vec/vector_scale_array.js";
import { clamp01 } from "../../../../../core/math/clamp01.js";
import { OctahedralUvEncoder } from "../../../impostors/octahedral/grid/OctahedralUvEncoder.js";

/**
 *
 * @param {number[]} result
 * @param {number} result_offset
 * @param {PathTracedScene} scene
 * @param {number} position_x
 * @param {number} position_y
 * @param {number} position_z
 * @param {number} max_depth
 * @param {number} resolution
 */
export function sh3_bake_depth(
    result, result_offset,
    scene,
    position_x, position_y, position_z,
    max_depth = 2,
    resolution = 12
) {

    const ray = new Ray3();
    const ray_hit = [];

    const basis = new Float32Array(9);
    const sh = new Float32Array(9);

    ray.origin.set(position_x, position_y, position_z);
    ray.tMax = max_depth;

    const encoder = new OctahedralUvEncoder();

    for (let y = 0; y < resolution; y++) {
        for (let x = 0; x < resolution; x++) {
            const u = x / (resolution - 1);
            const v = y / (resolution - 1);

            encoder.uv_to_unit(ray.direction, [u, v])

            let distance = scene.trace(ray_hit, ray);

            if (distance < 0) {
                distance = 100;
            }

            distance = clamp01(1 - distance / max_depth);

            sh3_basis_at(ray.direction.x, ray.direction.y, ray.direction.z, basis);

            sh3_vector_accumulate(
                sh, 0,
                basis, 0,
                [distance], 0, 1
            );

        }

    }

    // Note that we do not scale the depth samples by sphere surface area as we are not attempting to approximate radiance
    const normalization_weight = 1 / resolution * resolution;

    vector_scale_array(sh, 0, sh, 0, 27, normalization_weight);

    array_copy(sh, 0, result, result_offset, 9);
}