#version 330 core

// Interpolated values from the vertex shaders
#define iChannel0 inputtex
in vec2 UV;
uniform sampler2D inputtex;
uniform float iGlobalTime;
uniform float htoneamount;
uniform vec2 iResolution;

uniform sampler2D overlay;
uniform float overlayalpha;
uniform float basecolor;
uniform float letterboxw;
uniform float letterboxh;

uniform float wnoisec;
uniform float grainc;
uniform float keyvaluec;

// output
layout(location = 0) out vec4 color;


/////////////////////////////////
const float HOELDER_MAKINEN_MAGIC_CONSTANT = 2.0; //0.707;

mat2 rotate(float a) {
    return mat2(cos(a), sin(a), -sin(a), cos(a));
}

float intensity(vec4 color) {
    return dot(vec3(.2126, .7152, .0722), sqrt(color.rgb));
}

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

vec4 sampleme(vec2 uv) {
    
    vec2 unrotd = uv;
    
    float ar = (iResolution.y/iResolution.x);
    
    uv = rotate(42.5 * 3.141 / 180.0) * vec2(uv.x, uv.y*ar);
    float frequency = 200.0;
    vec2 nearest = 2.0*fract(frequency * uv ) - 1.0;
    
    
    float dist = length(nearest);
    float radius = intensity(texture2D(iChannel0, unrotd));
    vec4 white = 1.0 - vec4(1.0, 1.0, 1.0, 1.0);
    vec4 black = 1.0 - vec4(0.0, 0.0, 0.0, 1.0);
    return mix(black, white, step(radius, dist));
}

vec4 htone()
{
  vec2 uv = UV;
  vec4 fragcolor = sampleme(uv);
  for (int i = 0; i < 4; i++) {
      vec2 pt = uv + 0.5*rotate(20.0 + float(i) * HOELDER_MAKINEN_MAGIC_CONSTANT*3.141 / 4.0) * vec2(0.5, 0.0) / iResolution.xy;
      fragcolor += sampleme(pt);
  }
  fragcolor = fragcolor / 5.0;
  return fragcolor * texture(iChannel0, UV);
}
/////////////////////////////////






vec3 mod289(vec3 x) {
  return x - floor(x * (1.0 / 289.0)) * 289.0;
}

vec2 mod289(vec2 x) {
  return x - floor(x * (1.0 / 289.0)) * 289.0;
}

vec3 permute(vec3 x) {
  return mod289(((x*34.0)+1.0)*x);
}

float snoise(vec2 v){
  const vec4 C = vec4( 0.211324865405187,  // (3.0-sqrt(3.0))/6.0
             0.366025403784439,  // 0.5*(sqrt(3.0)-1.0)
            -0.577350269189626,  // -1.0 + 2.0 * C.x
             0.024390243902439); // 1.0 / 41.0
  vec2 i  = floor(v + dot(v, C.yy) );
  vec2 x0 = v -   i + dot(i, C.xx);
  vec2 i1;
  i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
  vec4 x12 = x0.xyxy + C.xxzz;
  x12.xy -= i1;
  i = mod289(i);
  vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) + i.x + vec3(0.0, i1.x, 1.0 ));
  vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
  m = m*m ;
  m = m*m ;
  vec3 x = 2.0 * fract(p * C.www) - 1.0;
  vec3 h = abs(x) - 0.5;
  vec3 ox = floor(x + 0.5);
  vec3 a0 = x - ox;
  m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
  vec3 g;
  g.x  = a0.x  * x0.x  + h.x  * x0.y;
  g.yz = a0.yz * x12.xz + h.yz * x12.yw;
  return 130.0 * dot(m, g);
}

// SPACEPOCH DIST EI ATM KAYTOSSA. ompas
vec2 co(vec2 uv)
{
  // return sampler-compatible uv coords
  // uv.y = -uv.y; // Remove this if image is upside down (tends to happen with video)
  return 0.5-uv*0.49;
}


vec4 colorgrade(vec4 color) {
  vec4 new = vec4(0.0);
  new.x = 1.2*pow(color.x, 1.75);
  new.y = pow(color.y+0.15, 0.75);
  new.z = pow(1.1*color.z+0.05, 1.3)+0.05;

  new += vec4(0.4);
  new /= 1.5;
  new.y -= 0.12;
  new.y = pow(new.y, 1.25);
  new = 1.2*pow(new, vec4(2.25));
  return  vec4(1.15*new.y, 0.9*pow(new.x, 0.95), 0.9*new.z, new.w);
}
/*
vec4 tonemap(vec4 color) {
  vec4 new = max(vec4(0.0), color-0.004);
    return (new*(new*6.2+0.5)) / (new*(new*6.2+1.7)+0.06);
}
*/
// Amount of distortion
const int N = 12;
//#define NOISE

float hash(float f)
{
  return fract(sin(f * 11.1753) * 192652.37862);
}

float noise(vec3 x)
{
    vec3 p = floor(x);
    vec3 f = fract(x);
    f       = f*f*(3.0-2.0*f);
    float n = p.x + p.y*57.0 + 113.0*p.z;
    return mix(mix(mix( hash(n+0.0),   hash(n+1.0),  f.x),
                   mix( hash(n+57.0),  hash(n+58.0), f.x),f.y),
               mix(mix( hash(n+113.0), hash(n+114.0),f.x),
                   mix( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);
}
/*
vec4 vhs(vec2 uv, sampler2D inputtex)
{
  float magnitude = 0.0009+0.0004*sin(iGlobalTime*1.231);
    vec3 sc = vec3(0.0);
    
    float b = smoothstep(0.0, 1.0, iGlobalTime/100.0);
    
    uv.y -= 0.05*smoothstep(0.85, 0.9, noise( vec3(iGlobalTime-uv.y*2.0, iGlobalTime, iGlobalTime)));
    //uv.x -= 1.0+0.1*smoothstep(0.8, 1.0, noise( vec3(iGlobalTime-sin(uv.y*6.0), iGlobalTime, iGlobalTime)));
    
    // Fucked up tape
    float flop = smoothstep(-0.75, 2.0, sin(0.15/noise(vec3(iGlobalTime*4.0))-1.0));
    float flip = smoothstep(-1.2, 1.5, sin(0.15/noise(vec3(iGlobalTime*3.7))-1.0));
    uv.y -= 0.06*flip-0.011;//pow(atan( 1.5+sin(iGlobalTime) ), 3.0);
    uv.x += 0.11*flop*pow(1.0/(1.5+uv.y), 2.0);
    
  // Loop a few passes for smoothness
  for(int i = 0; i < N; i++)
  {
    // Distortion magic via sampling offsets
    vec2 ruv = uv;
    ruv.x = uv.x - atan(( 1.0+sin(iGlobalTime*2.3), uv.y))*magnitude*1.25;
        ruv.x += 0.5*tan(rand(vec2(iGlobalTime*0.009,   uv.y )))*magnitude;

    vec2 guv = uv;
    guv.x  = uv.x - sin( tan( 0.2*(uv.y-1.0)*(uv.y-1.0)+iGlobalTime*2.1) )*magnitude*1.6;
    guv.x += 0.003*rand( vec2( tan( 0.01*uv.y+iGlobalTime ) ) );
    guv.x -= cos( tan( 0.2*(uv.y+1.0)*(uv.y+1.0)+iGlobalTime*0.9) )*magnitude*1.0;

    vec2 buv = uv;
    
        sc.r += 0.94*(1.55/float(N))*log(1.0+texture2D(inputtex, ruv).r);
        sc.g += 0.94*(1.19/float(N))*texture2D(inputtex,         guv ).g;
        sc.b += 0.94*(1.08/float(N))*sqrt(texture2D(inputtex,    buv ).b-0.1);  
        
    magnitude *= 1.25;
    uv *= 1.0015;
        uv -= 0.0006;
  }
    
    // More VHS color "correction" and playback noise
    sc = 0.12+0.85*sc + 0.08*noise( vec3(uv*321.7, 6853.1*(150.0+tan(iGlobalTime))+rand(uv*211.0)) ) ;
    float v  = 1.0 / pow(1.0 + 0.03*dot(uv, uv), 3.0); 
  float tv = 0.99+0.01*sin(100.0*iGlobalTime);
  return vec4(sc*v*tv,0);
}
*/

vec4 spacepochdist() {
  vec2 uv = 1.0 - 2.0 * UV;
  vec4 c = vec4(0); //vec4(0.0);

  float rf = 0.998;
  float gf = 1.0/0.998;
  
  float f = 1.0/float(N);
  for(int i = 0; i < N; ++i)
  {
    // sample texture
    c.x += f*texture(inputtex, co(gf*uv) ).x;
    c.y += f*texture(inputtex, co(uv) ).y;
    c.z += f*texture(inputtex, co(rf*uv) ).z;

    rf *= 0.9999;
    gf /= 0.9999;

    // distort radially
    //uv /= 1.0 + ( f*(0.03+0.0005*sin(iGlobalTime*12.0)*rand(uv) ) );
   // uv /= 1.0 + f*0.0001;
  }
  // vignette and flicker
  //float v  = 1.5 / pow(1.0 + 0.05*dot(uv, uv), 5.0); 
  float tv = 0.99+0.015*sin(2*3.141*25.0*iGlobalTime);
  return vec4( tv*c );
}

void main() {
  vec4 noiseval = vec4(0.0);
  if( (UV.y < letterboxh*0.1222 || UV.y > 1.0 - letterboxh*0.1222) ||
      (UV.x < letterboxw*0.1222 || UV.x > 1.0 - letterboxw*0.1222))  {
    color = vec4(vec3(0.0), 1.0);
  } else {
    //vec4 op = texture(inputtex, UV);
    noiseval = vec4(vec3(keyvaluec), 1.0);
    noiseval += vec4( wnoisec*0.01*vec3(rand(UV * vec2(iGlobalTime) )), 1.0 );
    noiseval += vec4( grainc*0.025*vec3(snoise(UV*400.0 + vec2(iGlobalTime*1000.0) )), 1.0 );

    vec4 op = vec4(0.0);
    op += spacepochdist(); //vec3(mod(row,2.0)*0.1),1.0)
    color = vec4(op.rgb, dot(op.rgb, vec3(0.2126, 0.7152, 0.0722)));
    color = htoneamount * htone() + (1.0 - htoneamount) * color;
  }
  color = basecolor * color + overlayalpha * texture(overlay, vec2(UV.x, 1.0 - UV.y)) + noiseval;
//  color = texture(inputtex, UV);
//  color = pow(color, vec4(1.0/2.2));
}