import LineBuilder from "../../../../../core/codegen/LineBuilder.js";
import { gaussian } from "../../../../../core/math/gaussian.js";

/**
 * Pre-build kernel internally, no branches in convolution code, everything is inlined
 * @param {number} samples
 * @param {number} distance
 * @returns {string}
 */
export function makeGaussianBlurShader({ samples = 5, distance = samples }) {
    const kernel_size = samples * samples;
    const sigma = (kernel_size - 1) / 6;

    const lb = new LineBuilder();

    lb.add('uniform vec2 resolution;');
    lb.add('uniform sampler2D tDiffuse;');
    lb.add('uniform sampler2D tMask;');
    lb.add('varying vec2 vUv;');

    const half_samples = (samples / 2) | 0;

    lb.add('void main(){');
    lb.indent();

    lb.add('if( texture2D(tMask, vUv).x < 1.0){ gl_FragColor = vec4(0.0); return; }');

    lb.add('vec2 pixel_uv = 1.0 / resolution;')
    lb.add('vec4 accumulator;')

    const scale_x = (distance / samples);
    const scale_y = (distance / samples);

    // prepare samples
    let total_value = 0;
    for (let iy = 0; iy < samples; iy++) {
        const fy = gaussian(sigma, iy - half_samples);
        const offset_y = (iy - half_samples) * scale_y;

        for (let ix = 0; ix < samples; ix++) {
            const fx = gaussian(sigma, ix - half_samples);
            const offset_x = (ix - half_samples) * scale_x;

            const value = fx * fy;

            total_value += value;

            lb.add(`accumulator += texture2D(tDiffuse, vUv + vec2(float(${offset_x}), float(${offset_y})) * pixel_uv) * float(${value});`);
        }
    }

    lb.add(`gl_FragColor = accumulator / ${total_value};`);

    lb.dedent();
    lb.add('}');

    return lb.build();
}
