import { clamp } from "../../../../core/math/clamp.js";
import { lerp } from "../../../../core/math/lerp.js";

/**
 *
 * @param {Float32Array} data
 * @param {number} res_x
 * @param {number} res_y
 * @param {number} res_z
 * @param {number} x
 * @param {number} y
 * @param {number} z
 * @return {number}
 */
export function scs3d_sample_linear(data, res_x, res_y, res_z, x, y, z) {
    const x_max = res_x - 1;
    const y_max = res_y - 1;
    const z_max = res_z - 1;

    const x_clamped = clamp(x, 0, x_max);
    const y_clamped = clamp(y, 0, y_max);
    const z_clamped = clamp(z, 0, z_max);

    const x0 = x_clamped | 0;
    const y0 = y_clamped | 0;
    const z0 = z_clamped | 0;

    const f_x = x_clamped - x0;
    const f_y = y_clamped - y0;
    const f_z = z_clamped - z0;

    const x1 = x_clamped === x0 ? x0 : x0 + 1;
    const y1 = y_clamped === y0 ? y0 : y0 + 1;
    const z1 = z_clamped === z0 ? z0 : z0 + 1;

    // get 8 points
    const z0_offset = z0 * (res_x * res_y);

    const y0_offset = y0 * res_x;

    const x0_offset = x0;
    const x1_offset = x1;

    const x0y0z0 = data[z0_offset + y0_offset + x0_offset];
    const x1y0z0 = data[z0_offset + y0_offset + x1_offset];

    const y1_offset = y1 * res_x;

    const x0y1z0 = data[z0_offset + y1_offset + x0_offset];
    const x1y1z0 = data[z0_offset + y1_offset + x1_offset];

    const z1_offset = z1 * (res_x * res_y);

    const x0y0z1 = data[z1_offset + y0_offset + x0_offset];
    const x1y0z1 = data[z1_offset + y0_offset + x1_offset];

    const x0y1z1 = data[z1_offset + y1_offset + x0_offset];
    const x1y1z1 = data[z1_offset + y1_offset + x1_offset];

    // filter on z0
    const lerp_z0_y0 = lerp(x0y0z0, x1y0z0, f_x);
    const lerp_z0_y1 = lerp(x0y1z0, x1y1z0, f_x);
    const lerp_z0 = lerp(lerp_z0_y0, lerp_z0_y1, f_y);

    // filter on z1
    const lerp_z1_y0 = lerp(x0y0z1, x1y0z1, f_x);
    const lerp_z1_y1 = lerp(x0y1z1, x1y1z1, f_x);
    const lerp_z1 = lerp(lerp_z1_y0, lerp_z1_y1, f_y);

    return lerp(lerp_z0, lerp_z1, f_z);
}
