import { float_to_uint8 } from "../../../../../core/binary/float_to_uint8.js";
import { clamp01 } from "../../../../../core/math/clamp01.js";
import { makeOnePixelTexture } from "../../../texture/makeOnePixelTexture.js";


/**
 *
 * @param {THREE.RawShaderMaterial} bake_material
 * @param {THREE.Material | THREE.MeshStandardMaterial} source_material
 * @param {Signal} cleanup_signal
 * @param {number} anisotropy
 */
export function prepare_bake_material({
                                          bake_material,
                                          source_material,
                                          cleanup_signal,
                                          anisotropy
                                      }) {


    const target_uniforms = bake_material.uniforms;


    let texture_diffuse = null;
    let texture_normal = null;
    let texture_roughness = null;
    let texture_metalness = null;
    let texture_occlusion = null;
    let texture_emissive = null;

    if (source_material.isMeshStandardMaterial) {
        texture_diffuse = source_material.map;
        texture_normal = source_material.normalMap;
        texture_roughness = source_material.roughnessMap;
        texture_metalness = source_material.metalnessMap;
        texture_occlusion = source_material.aoMap;
        texture_emissive = source_material.emissiveMap;


        if (texture_metalness === null) {
            const m = float_to_uint8(clamp01(source_material.metalness));
            texture_metalness = makeOnePixelTexture([m, m, m, 255], cleanup_signal);
        }

        if (texture_roughness === null) {
            const r = float_to_uint8(clamp01(source_material.roughness));

            texture_roughness = makeOnePixelTexture([r, r, r, 255], cleanup_signal);
        }

    } else {
        if (source_material.map !== undefined && source_material.map !== null) {
            texture_diffuse = source_material.map;
        }
    }

    if (texture_diffuse === null) {
        // plug white texture
        texture_diffuse = makeOnePixelTexture([255, 255, 255, 255], cleanup_signal);
    }
    if (texture_roughness === null) {
        texture_roughness = makeOnePixelTexture([255, 255, 255, 255], cleanup_signal);
    }

    if (texture_metalness === null) {
        texture_metalness = makeOnePixelTexture([0, 0, 0, 0], cleanup_signal);
    }

    if (texture_occlusion === null) {
        texture_occlusion = makeOnePixelTexture([255, 255, 255, 255], cleanup_signal);
    }

    if (texture_emissive === null) {
        texture_emissive = makeOnePixelTexture([0, 0, 0, 0], cleanup_signal);
    }

    // set rendering parameters on textures
    [
        texture_diffuse,
        texture_emissive,
        texture_occlusion,
        texture_metalness,
        texture_roughness,
        texture_normal
    ].forEach(t => {
        if (t === null) {
            return;
        }

        const _old_a = t.anisotropy;

        t.anisotropy = anisotropy;

        cleanup_signal.addOne(() => {
            t.anisotropy = _old_a;
        });
    });

    target_uniforms.tDiffuse.value = texture_diffuse;
    target_uniforms.tNormal.value = texture_normal;
    target_uniforms.tRoughness.value = texture_roughness;
    target_uniforms.tMetalness.value = texture_metalness;
    target_uniforms.tOcclusion.value = texture_occlusion;
    target_uniforms.tEmissive.value = texture_emissive;


    target_uniforms.color.value.copy(source_material.color);

    // TODO process texture transforms (offset, rotation, repeat)

    bake_material.side = source_material.side;

    bake_material.uniformsNeedUpdate = true;
}
