import { sampler2d_channel_linear_transform } from "./sampler2d_channel_linear_transform.js";

function compute_gradient_and_intercept_uint8(ctor) {
    let gradient = 1;
    let intercept = 0;

    switch (ctor) {
        case Uint16Array:
            gradient = 0.0038910505836575876;
            break;
        case Uint32Array:
            gradient = 5.937181414556033e-8;
            break;
        case Int8Array:
            gradient = 1;
            intercept = 127;
            break
        case Int16Array:
            gradient = 0.0038910505836575876;
            intercept = 127;
            break;
        case Int32Array:
            gradient = 5.937181414556033e-8;
            intercept = 127;
            break
        case Float32Array:
        case Float64Array:
            gradient = 255;
            break;
        default:
        // do nothing;
    }

    return {
        gradient, intercept
    }
}

/**
 * Many applications work with 8bit RGBA images, this utility function converts a given input to that format
 * @param {Sampler2D} input
 * @param {Sampler2D} output
 */
export function sampler2d_to_uint8_RGBA(output, input) {
    if (
        input.width !== output.width
        || input.height !== output.height
    ) {
        throw new Error('Dimensions of source and destination are incompatible');
    }

    if (output.itemSize !== 4) {
        throw new Error(`Destination must have 4 channels exactly, instead got '${output.itemSize}'`);
    }

    const { gradient, intercept } = compute_gradient_and_intercept_uint8(input.data.constructor);

    const source_item_size = input.itemSize;

    if (intercept === 0 && gradient === 1 && source_item_size === 4) {
        // already in the right format, use shortcut
        output.data.set(input.data);
        return;
    }

    if (source_item_size === 1) {

        // grayscale

        sampler2d_channel_linear_transform(output, input, 0, 0, gradient, intercept);
        sampler2d_channel_linear_transform(output, input, 1, 0, gradient, intercept);
        sampler2d_channel_linear_transform(output, input, 2, 0, gradient, intercept);

        output.channelFill(3, 255);

    } else if (source_item_size === 2) {

        // grayscale with alpha

        sampler2d_channel_linear_transform(output, input, 0, 0, gradient, intercept);
        sampler2d_channel_linear_transform(output, input, 1, 0, gradient, intercept);
        sampler2d_channel_linear_transform(output, input, 2, 0, gradient, intercept);
        sampler2d_channel_linear_transform(output, input, 3, 1, gradient, intercept);

    } else if (source_item_size === 3) {

        // RGB

        sampler2d_channel_linear_transform(output, input, 0, 0, gradient, intercept);
        sampler2d_channel_linear_transform(output, input, 1, 1, gradient, intercept);
        sampler2d_channel_linear_transform(output, input, 2, 2, gradient, intercept);

        output.channelFill(3, 255);

    } else if (source_item_size === 4) {

        // RGBA

        sampler2d_channel_linear_transform(output, input, 0, 0, gradient, intercept);
        sampler2d_channel_linear_transform(output, input, 1, 1, gradient, intercept);
        sampler2d_channel_linear_transform(output, input, 2, 2, gradient, intercept);
        sampler2d_channel_linear_transform(output, input, 3, 3, gradient, intercept);

    }
}
