'use strict'

modules['flare'] = {
    config: [
        ['offset', 'float2', [0, 0]],
        ['size', 'int', 500],
        ['pixelCoverage', 'float', 5],
        ['noiseScale', 'float', 0.02],
        ['noiseTime', 'float', 0],
        ['noiseMultiply', 'float', 1.4],
        ['noisePower', 'float', 8],
        ['noisePostAdd', 'float', 2.0],
        ['noisePostMultiply', 'float', 0.005],
    ],

    render: async (frameTime, self, config) => {
        const {
            offset,
            size,
            noiseScale,
            noiseTime,
            noiseMultiply,
            noisePower,
            noisePostAdd,
            noisePostMultiply,
        } = { ...config }
        const pixelCoverage = 1 / config.pixelCoverage

        const noiseGradient = []
        for (let i = 0; i < size; ++i) {
            let value = noise.simplex2(i * noiseScale / pixelCoverage, noiseTime) * .5 + .5
            value = Math.pow(value * noiseMultiply, noisePower)
            value += noisePostAdd
            value *= noisePostMultiply
            noiseGradient.push(value)
        }

        const buffer = greyscaleBuffers[getOutputBufferId()]

        const probeOffsets = [
            [-10, -10],
            [+10, -10],
            [+10, +10],
            [-10, +10],
            [-30, 0],
            [+30, 0],
            [0, -30],
            [0, +30],
        ]
        const visibility = probeOffsets.reduce((p, c) => {
            const probeX = Math.min(Math.max(320+offset[0] + c[0], 0), 639)
            const probeY = Math.min(Math.max(240+offset[1] + c[1], 0), 479)
            const visibility = Math.min(Math.max(1 - buffer[probeX + probeY*640], 0), 1)
            return p + visibility**2
        }, 0) / probeOffsets.length

        let index = 0
        for (let y = 0; y < 480; ++y) {
            const dy = y - 240-offset[1]
            for (let x = 0; x < 640; ++x) {
                const dx = x - 320-offset[0]
                const d = Math.sqrt(dx*dx + dy*dy) / visibility
                if (d < size) {
                    const v = noiseGradient[Math.floor(d*pixelCoverage)]
                    buffer[index] = v * visibility
                } else {
                    buffer[index] = 0
                }
                index++
            }
        }
        return
    }
}
