uniform int s_InputTex;
uniform int s_OrigTex;

uniform int uIterationCnt;
uniform int uCurrIter;
uniform bool uIsDownsampling;
uniform bool uIsUpsampling;

uniform float uThreshold;
uniform float uRamp;
uniform float uAmount;

in vec2 uv;
in vec2 uvn;
out vec4 C;

bool isThresholded = false;


int method = 1;

vec4 get(sampler2D tex, vec2 _uv){
    vec2 pxSz = 0.5/textureSize(tex, 0);
    //    _uv = clamp(_uv, 0., 1.0);
    _uv = clamp(
        _uv,
        vec2(0. + pxSz.x, 0. + pxSz.y),
        vec2(1. + pxSz.x, 1. + pxSz.y)
//        vec2(1. - pxSz.x, 1. - pxSz.y)
    );
    if (!isThresholded)
        return max(texture(tex, _uv), 0.001);
    else {
        vec4 t = texture(tex, _uv);
        t = max(t, 0.001);
        return t * smoothstep(uThreshold, uThreshold + uRamp, luma(t.xyz));
    }
}

vec4 blur(vec2 _uv, sampler2D tex, float stepSz){
    vec2 pxSz = 1./textureSize(tex, 0).xy;
    vec2 step = (pxSz*stepSz).xy;
    vec3 e = get(tex, _uv + step * vec2(0, 0)).rgb;

    if (! (uIsDownsampling && uCurrIter < 1)){
        step.y *= 0.7;
        step.x *= 2. + min(uCurrIter,6)*0.5;
    }
    if (method == 0){
        return (
        get(tex, _uv + step*vec2(-1, 1)) +
        get(tex, _uv + step*vec2(1, 1)) +
        get(tex, _uv + step*vec2(1, -1)) +
        get(tex, _uv + step*vec2(-1, -1))
        ) / 4.;
    } else {
        vec4 C = vec4(0);

        if (uIsDownsampling){
            vec3 a = get(tex, _uv + step * vec2(-2, 2)).rgb;
            vec3 b = get(tex, _uv + step * vec2(0, 2)).rgb;
            vec3 c = get(tex, _uv + step * vec2(2, 2)).rgb;

            vec3 d = get(tex, _uv + step * vec2(-2, 0)).rgb;
            vec3 f = get(tex, _uv + step * vec2(2, 0)).rgb;

            vec3 g = get(tex, _uv + step * vec2(-2, -2)).rgb;
            vec3 h = get(tex, _uv + step * vec2(0, -2)).rgb;
            vec3 i = get(tex, _uv + step * vec2(2, -2)).rgb;

            vec3 j = get(tex, _uv + step * vec2(-1, 1)).rgb;
            vec3 k = get(tex, _uv + step * vec2(1, 1)).rgb;
            vec3 l = get(tex, _uv + step * vec2(-1, -1)).rgb;
            vec3 m = get(tex, _uv + step * vec2(1, -1)).rgb;
            C.xyz = e*0.125;
            C.xyz += (a+c+g+i)*0.03125;
            C.xyz += (b+d+f+h)*0.0625;
            C.xyz += (j+k+l+m)*0.125;
        } else {
            vec3 a = get(tex, _uv + step * vec2(-1, 1)).rgb;
            vec3 b = get(tex, _uv + step * vec2(0, 1)).rgb;
            vec3 c = get(tex, _uv + step * vec2(1, 1)).rgb;

            vec3 d = get(tex, _uv + step * vec2(-1, 0)).rgb;
            vec3 f = get(tex, _uv + step * vec2(1, 0)).rgb;

            vec3 g = get(tex, _uv + step * vec2(-1, -1)).rgb;
            vec3 h = get(tex, _uv + step * vec2(0, -1)).rgb;
            vec3 i = get(tex, _uv + step * vec2(1, -1)).rgb;

            C.xyz = e*4.0;
            C.xyz += (b+d+f+h)*2.0;
            C.xyz += (a+c+g+i);
            C.xyz *= 1.0 / 16.0;
        }

        return C;
    }
}

vec3 sample_chromab(sampler2D t, vec2 uv, vec2 dist_dir){
    vec3 s = vec3(0);
//    dist_dir *= 0.1;
    float iters = 5.;
    for(float i = 0.; i < iters; i++){
        float idx = i/iters;
        s.r += texture(t, uv + dist_dir * idx).r;
        s.g += texture(t, uv + dist_dir * idx*1.1).g;
        s.b += texture(t, uv + dist_dir * idx*0.9).b;
    }
    return s/iters;
}

void main() {
    //    vec2 uv = uvn;
    //    vec2 uv = uvn;
    if (uCurrIter == uIterationCnt*2 - 1){
        // Final step.
        vec3 flare_col = vec3(0.5, 0.7, 1);
        flare_col *= flare_col;
        C = texture(textures[s_OrigTex], uvn)
            + blur(uvn, textures[s_InputTex], 0.5)*uAmount * vec4(flare_col, 1)
        ;
        //        C = texture(textures[s_OrigTex], uvn);
        vec2 u = uv;
        float att = dot(uv*0.5 - .0, uv*0.5 - .0);
        //        u = -u;
        //        vec2 offs = vec2(0);
        for (float i = 1; i < 6; i++){
            //            u = 1.-u;
            u = -u;
            u *= 0.5;
            float offs_fac = 1.-1./i;
            offs_fac *= offs_fac;
            offs_fac *= offs_fac;
            offs_fac *= offs_fac;
            u += 0.05 * i * (1.-mod(i+1, 2)*2.0)*offs_fac;
            u.y *= (1.-offs_fac*offs_fac)*1.2;


            int tex_idx = 1;

            vec2 q = u;
//            q.y *= (1.-offs_fac)*1.4;
            if (i ==3){
                //                q += 0.5;
                q *= 5.;
                q.y *= 1.;
                q.x *= 0.3;
                tex_idx = 0;
//                                q = clamp(q, 0,1);
                //                q -= 0.5;
            }
            if(i == 5){
                q *= 0.2;
            }
            //            vec2 q = u*0.5 + 0.5;
            q *= 1. + att*0.6;
            q = q*0.5 + 0.5;

            vec3 flare_col = vec3(0.5, 0.7, 1);
            flare_col = 0.5 + sin(flare_col*1. - sin(vec3(3,2,1)*i)*0.4);
            flare_col *= flare_col;
            //            q = fract(q);
            //            q.y *= 1. + 1./pow(0.5 + 0.5*sin(i*2.4),0.5)*0.2;
            C.rgb += max(1.-att*1.7,0.)
//                * texture(textures[s_InputTex + tex_idx], q)
//                * sample_chromab(textures[s_InputTex + tex_idx], q, -normalize(uv - 0.5 + q*0.2)*0.04)
                * sample_chromab(textures[s_InputTex + tex_idx], q, normalize(q)*0.04)
                *0.2 / pow(float(i+1.0), 1.9)
                * flare_col * uAmount*0.3;
        }

        if (false){
            float halo_rad = 0.5;
            vec2 q = uvn;
            q -= 0.5;
            q = -q;
            vec2 dist_dir = normalize(q);
            q = q - dist_dir*halo_rad;

            q *= rot(length(q)*45.);

            float halo_att = smoothstep(0.1,0., abs(length(q)));
            q += 0.5;
//            q = vec2(atan(q.y,q.x),length(q));
            vec3 s = uAmount * flare_col * 0.1 * halo_att * sample_chromab(textures[s_InputTex + 1], q, dist_dir*0.4);
            C.rgb += s;

        }
        C.a = 1.;
    } else if (uIsDownsampling){
        // Downsample step.
        if (uCurrIter == 0){
            isThresholded = true;
        }
        C = blur(uvn, textures[s_InputTex], 1.);
        C.a = 1.;
    } else if (uIsUpsampling){
        // Upsampling step.
        C = blur(uvn, textures[s_InputTex], 0.5);
        C.a = 1.;
    }
}
