import { uint8_to_float } from "../../../../binary/uint8_to_float.js";

/**
 *
 * @param {number} barycentric_x
 * @param {number} barycentric_y
 * @returns {number}
 */
export function triangle_encode_rasterized_depth(barycentric_x, barycentric_y) {
    const sampleY = (barycentric_y * 4.0) >>> 0;
    const sampleX = (barycentric_x * 4.0) >>> 0;

    const baseIndex = ((((11.0 - sampleY) * sampleY) * 0.5 + sampleX + 0.5)) >>> 0;
    const lineLength = 5 - sampleY;

    const baseBary_x = sampleX * 0.25;
    const baseBary_y = sampleY * 0.25;

    let indices_0 = baseIndex + 1;
    let indices_1 = baseIndex + lineLength;
    let indices_2 = baseIndex;

    // figure out barycentric coordinates within the triangular sample, this will be needed for bilinear interpolation

    let sampleBary_x = (barycentric_x - baseBary_x) * 4.0;
    let sampleBary_y = (barycentric_y - baseBary_y) * 4.0;

    const above = sampleBary_x + sampleBary_y > 1.0;

    if (above) {
        // above the diagonal
        indices_0 = baseIndex + lineLength;
        indices_1 = baseIndex + 1;
        indices_2 = baseIndex + lineLength + 1;

        const newSampleBary_x = -(sampleBary_y - 1.0);
        const newSampleBary_y = -(sampleBary_x - 1.0);

        sampleBary_x = newSampleBary_x;
        sampleBary_y = newSampleBary_y;
    }

    const sampleBary_z = 1.0 - sampleBary_x - sampleBary_y;

    return indices_0;

    if (sampleBary_x > sampleBary_y && sampleBary_x > sampleBary_z) {
        return above ? indices_1 : indices_0;
    } else if (sampleBary_y > sampleBary_z && sampleBary_y > sampleBary_x) {
        return above ? indices_0 : indices_1;
    } else {
        return indices_2;
    }
}

/**
 *
 * @param {Uint32Array} encodedDepth
 * @param {number} input_offset
 * @param {number} index
 * @return {number}
 */
function decode_index(encodedDepth, input_offset, index) {
    const encoded_index_0 = index >>> 2;
    const encoded_index_1 = index & 3;

    const uint8 = (encodedDepth[input_offset + encoded_index_0] >> ((encoded_index_1) * 8)) & 0xFF;

    return uint8_to_float(uint8);
}

export function triangle_decode_depth(encodedDepth, input_offset, barycentric_x, barycentric_y) {
    const sampleY = (barycentric_y * 4.0) >>> 0;
    const sampleX = (barycentric_x * 4.0) >>> 0;

    const baseIndex = ((((11.0 - sampleY) * sampleY) * 0.5 + sampleX + 0.5)) >>> 0;
    const lineLength = 5 - sampleY;

    const baseBary_x = sampleX * 0.25;
    const baseBary_y = sampleY * 0.25;

    let indices_0 = baseIndex + 1;
    let indices_1 = baseIndex + lineLength;
    let indices_2 = baseIndex;

    // figure out barycentric coordinates within the triangular sample, this will be needed for bilinear interpolation

    let sampleBary_x = (barycentric_x - baseBary_x) * 4.0;
    let sampleBary_y = (barycentric_y - baseBary_y) * 4.0;

    const above = sampleBary_x + sampleBary_y > 1.0;

    if (above) {
        // above the diagonal
        // indices_0 = baseIndex + lineLength;
        // indices_1 = baseIndex + 1;
        indices_2 = baseIndex + lineLength + 1;

        const newSampleBary_x = -(sampleBary_y - 1.0);
        const newSampleBary_y = -(sampleBary_x - 1.0);

        sampleBary_x = newSampleBary_x;
        sampleBary_y = newSampleBary_y;
    }

    const sampleBary_z = 1.0 - sampleBary_x - sampleBary_y;

    // perform bilinear interpolation of depth
    return sampleBary_x * decode_index(encodedDepth, input_offset, indices_0)
        + sampleBary_y * decode_index(encodedDepth, input_offset, indices_1)
        + sampleBary_z * decode_index(encodedDepth, input_offset, indices_2);
}