/**
 *
 *
 * c1 = 0.42904276540489171563379376569857;    // 4 * Â2.Y22 = 1/4 * sqrt(15.PI)
 * c2 = 0.51166335397324424423977581244463;    // 0.5 * Â1.Y10 = 1/2 * sqrt(PI/3)
 * c3 = 0.24770795610037568833406429782001;    // Â2.Y20 = 1/16 * sqrt(5.PI)
 * c4 = 0.88622692545275801364908374167057;    // Â0.Y00 = 1/2 * sqrt(PI)
 *
 * @see https://github.com/mrdoob/three.js/blob/d081c5a3501d272d19375fab1b01fedf9df29b22/src/math/SphericalHarmonics3.js#L85
 * @see https://graphics.stanford.edu/papers/envmap/envmap.pdf
 * @see https://www.ppsloan.org/publications/StupidSH36.pdf
 *
 * @param {number[]} result Result will be written here
 * @param {number} result_offset
 * @param {number[]} harmonics coefficients are read from here
 * @param {number} harmonics_offset offset into coefficients array where to start reading the data
 * @param {number} dimension_count number of encoded dimensions, this is essentially a shortcut for multiple harmonics being read at the same time, such as with RGB values
 * @param {number[]} direction 3d vector read from here, we will read 3 values from here to sample spherical harmonic, direction is assumed to be normalized
 * @param {number} direction_offset offset into direction array
 */
export function sh3_sample_irradiance_by_direction(
    result, result_offset,
    harmonics, harmonics_offset,
    dimension_count,
    direction, direction_offset
) {
    const x = direction[direction_offset];
    const y = direction[direction_offset + 1];
    const z = direction[direction_offset + 2];

    let channel_value;

    for (let i = 0; i < dimension_count; i++) {

        // band 0
        channel_value = harmonics[harmonics_offset + i] * 0.88622692545275801364908374167057;

        // band 1
        channel_value -= harmonics[harmonics_offset + dimension_count + i] * 2.0 * 0.51166335397324424423977581244463 * y;
        channel_value += harmonics[harmonics_offset + dimension_count * 2 + i] * 2.0 * 0.51166335397324424423977581244463 * z;
        channel_value -= harmonics[harmonics_offset + dimension_count * 3 + i] * 2.0 * 0.51166335397324424423977581244463 * x;

        // band 2
        channel_value += harmonics[harmonics_offset + dimension_count * 4 + i] * 2.0 * 0.42904276540489171563379376569857 * x * y;
        channel_value -= harmonics[harmonics_offset + dimension_count * 5 + i] * 2.0 * 0.42904276540489171563379376569857 * y * z;
        channel_value += harmonics[harmonics_offset + dimension_count * 6 + i] * (3 * z * z - 1) * 0.24770795610037568833406429782001;
        channel_value -= harmonics[harmonics_offset + dimension_count * 7 + i] * 2.0 * 0.42904276540489171563379376569857 * x * z;
        channel_value += harmonics[harmonics_offset + dimension_count * 8 + i] * 0.42904276540489171563379376569857 * (x * x - y * y);

        // write out
        result[result_offset + i] = channel_value;
    }
}
