#extension GL_OES_EGL_image_external : require
precision mediump float;

uniform samplerExternalOES uObject;
uniform sampler2D uSampler;
uniform float uAlpha;

varying vec2 vTextureCoord;
varying vec2 vTextureObjectCoord;
uniform mediump float uXFactor;
uniform mediump float uYFactor;
uniform vec3 iResolution;
uniform float uBlur;
uniform float uRadius;
uniform mediump float uSelect;
uniform mediump sampler2D uSampler2;
const highp vec3 W = vec3(0.299,0.587,0.114);
vec2 blurCoordinates[24];
uniform vec2 uResolution;

float hardLight(float color) {
  if(color <= 0.5) {
    color = color * color * 2.0;
  } else {
    color = 1.0 - ((1.0 - color)*(1.0 - color) * 2.0);
  }
  return color;
}

vec4 sampleAs3DTexture(vec3 uv) {
  float width = 16.;
  float sliceSize = 1.0 / width;
  float slicePixelSize = sliceSize / width;
  float sliceInnerSize = slicePixelSize * (width - 1.0);
  float zSlice0 = min(floor(uv.z * width), width - 1.0);
  float zSlice1 = min(zSlice0 + 1.0, width - 1.0);
  float xOffset = slicePixelSize * 0.5 + uv.x * sliceInnerSize;
  float s0 = xOffset + (zSlice0 * sliceSize);
  float s1 = xOffset + (zSlice1 * sliceSize);
  vec4 slice0Color = texture2D(uSampler2, vec2(s0, uv.y));
  vec4 slice1Color = texture2D(uSampler2, vec2(s1, uv.y));
  float zOffset = mod(uv.z * width, 1.0);
  vec4 result = mix(slice0Color, slice1Color, zOffset);
  return result;
}

void main() {
  float Pi = 6.28318530718;
  float Directions = 16.0;
  float Quality = 6.0;
  float Size = 32.0;
  vec2 Radius = Size/iResolution.xy;
  float threshold = 0.0;

  vec2 rotateCoords = vTextureObjectCoord;
  float sin_factor = sin(25.12);
  float cos_factor = cos(25.12);
  rotateCoords = vec2((rotateCoords.x - 0.5) , rotateCoords.y - 0.5);
  rotateCoords *= mat2(-cos_factor , sin_factor, sin_factor, cos_factor);
  rotateCoords *= vec2(uXFactor, uYFactor);
  rotateCoords += 0.5;

  vec4 samplerPixel = texture2D(uSampler, vTextureCoord);

  if (vTextureObjectCoord.x < 0.0 || vTextureObjectCoord.x > 1.0 ||
      vTextureObjectCoord.y < 0.0 || vTextureObjectCoord.y > 1.0) {
      gl_FragColor = samplerPixel;
  } else {
    if (uSelect == 1.0){
      vec4 objectPixel = texture2D(uObject, rotateCoords);
      gl_FragColor = vec4(mix(samplerPixel.rgb, objectPixel.rgb, objectPixel.a * uAlpha), 1.0);

    } else if (uSelect == 2.0){
      vec3 objectPixel = texture2D(uObject, rotateCoords).rgb;

      blurCoordinates[0] = rotateCoords.xy + uResolution * vec2(0.0, -10.0);
      blurCoordinates[1] = rotateCoords.xy + uResolution * vec2(0.0, 10.0);
      blurCoordinates[2] = rotateCoords.xy + uResolution * vec2(-10.0, 0.0);
      blurCoordinates[3] = rotateCoords.xy + uResolution * vec2(10.0, 0.0);
      blurCoordinates[4] = rotateCoords.xy + uResolution * vec2(5.0, -8.0);
      blurCoordinates[5] = rotateCoords.xy + uResolution * vec2(5.0, 8.0);
      blurCoordinates[6] = rotateCoords.xy + uResolution * vec2(-5.0, 8.0);
      blurCoordinates[7] = rotateCoords.xy + uResolution * vec2(-5.0, -8.0);
      blurCoordinates[8] = rotateCoords.xy + uResolution * vec2(8.0, -5.0);
      blurCoordinates[9] = rotateCoords.xy + uResolution * vec2(8.0, 5.0);
      blurCoordinates[10] = rotateCoords.xy + uResolution * vec2(-8.0, 5.0);
      blurCoordinates[11] = rotateCoords.xy + uResolution * vec2(-8.0, -5.0);
      blurCoordinates[12] = rotateCoords.xy + uResolution * vec2(0.0, -6.0);
      blurCoordinates[13] = rotateCoords.xy + uResolution * vec2(0.0, 6.0);
      blurCoordinates[14] = rotateCoords.xy + uResolution * vec2(6.0, 0.0);
      blurCoordinates[15] = rotateCoords.xy + uResolution * vec2(-6.0, 0.0);
      blurCoordinates[16] = rotateCoords.xy + uResolution * vec2(-4.0, -4.0);
      blurCoordinates[17] = rotateCoords.xy + uResolution * vec2(-4.0, 4.0);
      blurCoordinates[18] = rotateCoords.xy + uResolution * vec2(4.0, -4.0);
      blurCoordinates[19] = rotateCoords.xy + uResolution * vec2(4.0, 4.0);
      float sampleColor = objectPixel.g * 22.0;
      sampleColor += texture2D(uObject, blurCoordinates[0]).g;
      sampleColor += texture2D(uObject, blurCoordinates[1]).g;
      sampleColor += texture2D(uObject, blurCoordinates[2]).g;
      sampleColor += texture2D(uObject, blurCoordinates[3]).g;
      sampleColor += texture2D(uObject, blurCoordinates[4]).g;
      sampleColor += texture2D(uObject, blurCoordinates[5]).g;
      sampleColor += texture2D(uObject, blurCoordinates[6]).g;
      sampleColor += texture2D(uObject, blurCoordinates[7]).g;
      sampleColor += texture2D(uObject, blurCoordinates[8]).g;
      sampleColor += texture2D(uObject, blurCoordinates[9]).g;
      sampleColor += texture2D(uObject, blurCoordinates[10]).g;
      sampleColor += texture2D(uObject, blurCoordinates[11]).g;
      sampleColor += texture2D(uObject, blurCoordinates[12]).g * 2.0;
      sampleColor += texture2D(uObject, blurCoordinates[13]).g * 2.0;
      sampleColor += texture2D(uObject, blurCoordinates[14]).g * 2.0;
      sampleColor += texture2D(uObject, blurCoordinates[15]).g * 2.0;
      sampleColor += texture2D(uObject, blurCoordinates[16]).g * 2.0;
      sampleColor += texture2D(uObject, blurCoordinates[17]).g * 2.0;
      sampleColor += texture2D(uObject, blurCoordinates[18]).g * 2.0;
      sampleColor += texture2D(uObject, blurCoordinates[19]).g * 2.0;
      sampleColor += texture2D(uObject, blurCoordinates[20]).g * 3.0;
      sampleColor += texture2D(uObject, blurCoordinates[21]).g * 3.0;
      sampleColor += texture2D(uObject, blurCoordinates[22]).g * 3.0;
      sampleColor += texture2D(uObject, blurCoordinates[23]).g * 3.0;
      sampleColor = sampleColor / 62.0;

      float highPass = objectPixel.g - sampleColor + 0.5;

      for (int i = 0; i < 5;i++)
      {
        highPass = hardLight(highPass);
      }
      float luminance = dot(objectPixel, W);
      float alpha = pow(luminance, 0.33);
      vec3 smoothColor = objectPixel + (objectPixel-vec3(highPass))*alpha*0.1;
      vec3 beautyRet = mix(smoothColor.rgb, max(smoothColor, objectPixel), alpha);

      vec4 pixel4 = vec4(beautyRet, 1.0);
      vec3 mixed = mix(samplerPixel.rgb, pixel4.rgb,pixel4.a * uAlpha);
      gl_FragColor = vec4(mixed,1.0);
    }else  if (uSelect == 3.0){
      vec4 objectPixel = texture2D(uObject, rotateCoords);
      vec4 gradedPixel = sampleAs3DTexture(objectPixel.rgb);
      gradedPixel.a = objectPixel.a;
      vec3 mixed = mix(samplerPixel.rgb, gradedPixel.rgb, gradedPixel.a * uAlpha);
      gl_FragColor = vec4(mixed,1.0);
    }else if (uSelect == 4.0){
      lowp vec4 textureColor;
      lowp vec4 textureColorRes;
      lowp vec4 textureColorOri;
      vec4 grey1Color;
      vec4 layerColor;
      mediump float satVal = 115.0 / 100.0;

      float xCoordinate = rotateCoords.x;
      float yCoordinate = rotateCoords.y;
      highp float redCurveValue;
      highp float greenCurveValue;
      highp float blueCurveValue;

      textureColor = texture2D( uObject, vec2(xCoordinate, yCoordinate));
      textureColorRes = textureColor;
      textureColorOri = textureColor;

      textureColor = 1.0 - ((1.0 - textureColorOri) * (1.0 - textureColorOri));
      textureColor = (textureColor - textureColorOri) + textureColorOri;

      redCurveValue = texture2D(uSampler2, vec2(textureColor.r, 0.0)).r;
      greenCurveValue = texture2D(uSampler2, vec2(textureColor.g, 0.0)).g;
      blueCurveValue = texture2D(uSampler2, vec2(textureColor.b, 0.0)).b;

      highp float G = (redCurveValue + greenCurveValue + blueCurveValue);
      G = G / 3.0;

      redCurveValue = ((1.0 - satVal) * G + satVal * redCurveValue);
      greenCurveValue = ((1.0 - satVal) * G + satVal * greenCurveValue);
      blueCurveValue = ((1.0 - satVal) * G + satVal * blueCurveValue);

      textureColor = vec4(redCurveValue, greenCurveValue, blueCurveValue, 1.0);
      vec4 texColor = vec4(textureColor.r, textureColor.g, textureColor.b, 1.0);

      vec3 mixed = mix(samplerPixel.rgb, texColor.rgb, texColor.a * uAlpha);
      gl_FragColor = vec4(mixed,1.0);
    }else if (uSelect == 5.0){
      vec4 objectPixel = texture2D(uObject, rotateCoords);
      vec3 maxValue = vec3(0.,0.,0.);
      for(int i = -2; i<=1; i++)
      {
        for(int j = -2; j<=1; j++)
        {
          vec4 tempColor = texture2D(uObject, rotateCoords+vec2(0.00052, 0.000926)*vec2(i,j));
          maxValue.r = max(maxValue.r,tempColor.r);
          maxValue.g = max(maxValue.g,tempColor.g);
          maxValue.b = max(maxValue.b,tempColor.b);
          threshold += dot(tempColor.rgb, W);
        }
      }
      float gray1 = dot(objectPixel.rgb, W);
      float gray2 = dot(maxValue, W);
      float contour = gray1 / gray2;
      threshold = threshold / 25.;
      float alpha = max(1.0,gray1>threshold?1.0:(gray1/threshold));
      float result = contour * alpha + (1.0-alpha)*gray1;
      vec4 grayRet = vec4(vec3(result,result,result), objectPixel.w);
      vec3 mixed = mix(samplerPixel.rgb, objectPixel.rgb, objectPixel.a * uAlpha);

      vec3 mixRet = mix(mixed.rgb, grayRet.rgb, objectPixel.a * uAlpha);
      gl_FragColor = vec4(mixRet,1.0);
    }else{
      vec4 sum = vec4(.0);
      if (uBlur > 0.0) {
        for (float d=0.0; d<Directions; d++) {
          for (float i=1.0; i<=Quality; i++) {
            sum += texture2D(uObject, rotateCoords + vec2(cos(d), sin(d)) * Radius*i);
          }
        }
      } else {
        sum = texture2D(uObject, rotateCoords);
      }
      sum /= Quality * Directions - 15.0;
      vec3 mixed = mix(samplerPixel.rgb, sum.rgb, samplerPixel.a * uAlpha);
      gl_FragColor = vec4(mixed.rgb+vec3(0.0), sum.w);
    }
  }
}
