import { max2 } from "../../../../../core/math/max2.js";
import { assert } from "../../../../../core/assert.js";

/**
 * Relatively slow, but handles all cases
 * @param {Sampler2D} input
 * @param {Sampler2D} output
 */
export function sampler2d_scale_generic(input, output) {
    assert.defined(input, 'input');
    assert.defined(output, 'output');

    const target_width = output.width;
    const target_height = output.height;

    // build kernel

    const u_scale = input.width / target_width;
    const v_scale = input.height / target_height;

    const kernel_width = max2(1, Math.ceil(u_scale));
    const kernel_height = max2(1, Math.ceil(v_scale));

    const kernel_size = kernel_width * kernel_height;
    const kernel_size_inv = 1 / kernel_size;

    const itemSize = input.itemSize;

    const sample = new Float32Array(itemSize);

    let column_index;
    let row_index;
    let k_y;
    let k_x;
    let i;

    for (column_index = 0; column_index < target_height; column_index++) {

        const source_y = column_index * v_scale;

        for (row_index = 0; row_index < target_width; row_index++) {

            // figure out source offset
            const source_x = row_index * u_scale;

            const output_texel_address = (column_index * target_width + row_index) * itemSize;

            // accumulate kernel samples
            for (k_y = 0; k_y < kernel_height; k_y++) {

                for (k_x = 0; k_x < kernel_width; k_x++) {

                    for (i = 0; i < itemSize; i++) {
                        sample[i] += input.sampleChannelBilinear(source_x + k_x, source_y + k_y, i);
                    }

                }
            }

            for (i = 0; i < itemSize; i++) {
                // dilute sample
                output.data[output_texel_address + i] = sample[i] * kernel_size_inv;

                //reset sample
                sample[i] = 0;
            }

        }
    }
}
