import { clamp } from "../math/clamp.js";
import { max3 } from "../math/max3.js";

/**
 * Convert floating point RGB input to RGBE9995 Uint32 value
 * TODO unverified
 * @param {number} r
 * @param {number} g
 * @param {number} b
 * @returns {number} Uint32
 */
export function rgb_to_rgbe9995(r, g, b) {

    //see https://github.com/Stary2001/godot/blob/00c6ce9716ed542997bc2b59136bceb3729db970/core/color.h#L125

    const pow2to9 = 512.0;
    const B = 15.0;
    //const float Emax = 31.0f;
    const N = 9.0;

    const sharedexp = 65408.000; //(( pow2to9  - 1.0f)/ pow2to9)*powf( 2.0f, 31.0f - 15.0f);

    const cRed = clamp(r, 0, sharedexp);
    const cGreen = clamp(g, 0, sharedexp);
    const cBlue = clamp(b, 0, sharedexp);

    const cMax = max3(cRed, cGreen, cBlue);

    if(cMax === 0){
        // perfect black
        return 0;
    }

    // expp = MAX(-B - 1, log2(maxc)) + 1 + B

    const expp = Math.max(-B - 1.0, Math.floor(Math.log2(cMax))) + 1.0 + B;

    const sMax = Math.floor((cMax / Math.pow(2.0, expp - B - N)) + 0.5);

    let exps = expp + 1.0;

    if (0.0 <= sMax && sMax < pow2to9) {
        exps = expp;
    }

    const denominator = Math.pow(2.0, exps - B - N);

    const sRed = Math.floor((cRed / denominator) + 0.5) >>> 0;
    const sGreen = Math.floor((cGreen / denominator) + 0.5) >>> 0;
    const sBlue = Math.floor((cBlue / denominator) + 0.5) >>> 0;

    const result = (sRed & 0x1FF)
        | ((sGreen & 0x1FF) << 9)
        | ((sBlue & 0x1FF) << 18)
        | ((exps & 0x1F) << 27);

    return result >>> 0; // force Uint32

}