import { assert } from "../../../../core/assert.js";
import { Sampler2D } from "./Sampler2D.js";
import { sampler2d_write_to_canvas_raw } from "./sampler2d_write_to_canvas_raw.js";

/**
 *
 * @param {Sampler2D} sampler
 * @param {Number} [scale]
 * @param {Number} [offset]
 * @param {HTMLCanvasElement} [canvas] if no canvas is supplied, a new one will be created
 * @returns {HTMLCanvasElement} canvas
 */
export function sampler2d_to_html_canvas(
    sampler,
    scale = 255,
    offset = 0,
    canvas = document.createElement("canvas")
) {
    assert.defined(sampler, 'sampler');

    assert.isNumber(scale, 'scale');
    assert.notNaN(scale, 'scale');

    assert.isNumber(offset, 'offset');
    assert.notNaN(offset, 'offset');

    assert.defined(canvas, 'canvas');

    const source_data = sampler.data;

    const converted_sampler = Sampler2D.uint8clamped(4, sampler.width, sampler.height);

    const width = sampler.width;
    const height = sampler.height;

    const array = converted_sampler.data;
    //
    const source_channel_count = sampler.itemSize;
    if (source_channel_count === 4 && offset === 0 && scale === 1) {
        // shortcut or straight forward case
        array.set(source_data);
    } else {
        if (source_channel_count < 4) {
            //sampler lacks alpha channel, set alpha values to fully opaque
            const n = width * height * 4;

            for (let i = 3; i < n; i += 4) {
                array[i] = 255;
            }

        }


        if (source_channel_count === 1) {
            let index = 0;
            for (let y = 0; y < height; y++) {
                for (let x = 0; x < width; x++) {
                    const texel_address = (y * width + x);

                    const source_value = source_data[texel_address];
                    const transformed_value = Math.round((source_value + offset) * scale);

                    // write identical RGB for grayscale image
                    array[index + 0] = transformed_value;
                    array[index + 1] = transformed_value;
                    array[index + 2] = transformed_value;


                    index += 4;
                }
            }
        } else {

            let index = 0;
            for (let y = 0; y < height; y++) {
                for (let x = 0; x < width; x++) {
                    const texel_address = (y * width + x) * source_channel_count;

                    for (let i = 0; i < source_channel_count; i++) {
                        const source_value = source_data[texel_address + i];
                        const transformed_value = Math.round((source_value + offset) * scale);
                        array[index + i] = transformed_value;
                    }


                    index += 4;
                }
            }
        }

    }

    sampler2d_write_to_canvas_raw(converted_sampler, canvas);

    return canvas;
}

export default sampler2d_to_html_canvas;
