
import Filter from '../Filter';
import { defaultVert } from '../defaultVerts';

const noiseFrag =
    "precision mediump float;" +

    "varying vec2 vTextureCoord;" +
    "varying vec4 vColor;" +

    "uniform float uNoise;" +
    "uniform float uSeed;" +
    "uniform sampler2D uSampler;" +

    "float rand(vec2 co){" +
    "return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);" +
    "}" +

    "void main(){" +
    "vec4 color = texture2D(uSampler, vTextureCoord);" +
    "float randomValue = rand(gl_FragCoord.xy * uSeed);" +
    "float diff = (randomValue - 0.5) * uNoise;" +

    // Un-premultiply alpha before applying the color matrix. See issue #3539.
    "if (color.a > 0.0) {" +
    "color.rgb /= color.a;" +
    "}" +

    "color.r += diff;" +
    "color.g += diff;" +
    "color.b += diff;" +

    // Premultiply alpha again.
    "color.rgb *= color.a;" +

    "gl_FragColor = color;" +
    "}"



/**
 * @author Vico @vicocotea
 * original filter: https://github.com/evanw/glfx.js/blob/master/src/filters/adjust/noise.js
 */

/**
 * A Noise effect filter.
 *
 * @class
 * @extends Filter
 * @memberof filters
 */
export default class NoiseFilter extends Filter {
    /**
     * @param {number} noise - The noise intensity, should be a normalized value in the range [0, 1].
     * @param {number} seed - A random seed for the noise generation. Default is `Math.random()`.
     */
    constructor(noise: number = 0.5, seed: number = Math.random()) {
        super(defaultVert, noiseFrag);
        this.noise = noise;
        this.seed = seed;
    }

    /**
     * The amount of noise to apply, this value should be in the range (0, 1].
     *
     * @member {number}
     * @default 0.5
     */
    get noise() {
        return this.uniforms.uNoise;
    }

    set noise(value) {
        this.uniforms.uNoise = value;
    }

    /**
     * A seed value to apply to the random noise generation. `Math.random()` is a good value to use.
     *
     * @member {number}
     */
    get seed() {
        return this.uniforms.uSeed;
    }

    set seed(value) {
        this.uniforms.uSeed = value;
    }
}
