precision mediump float;
uniform sampler2D inputTexture;
varying vec2 textureCoordinate;

const lowp vec3 luminanceWeighting = vec3(0.3, 0.3, 0.3);

float getLuma(vec3 rgbP) {
    return (0.299 * rgbP.r) + (0.587 * rgbP.g) + (0.114 * rgbP.b);
}

vec3 rgbToYuv(vec3 inP) {
    float luma = getLuma(inP);
    return vec3(luma, (1.0 / 1.772) * (inP.b - luma), (1.0 / 1.402) * (inP.r - luma));
}

vec3 yuvToRgb(vec3 inP) {
    return vec3(1.402 * inP.b + inP.r, (inP.r - (0.299 * 1.402 / 0.587) * inP.b - (0.114 * 1.772 / 0.587) * inP.g), 1.772 * inP.g + inP.r);
}

vec3 fadeAdjust(vec3 color, float fadeVal) {
    return (color * (1.0 - fadeVal)) + ((color + (vec3(-0.9772) * pow(vec3(color), vec3(3.0)) + vec3(1.708) * pow(vec3(color), vec3(2.0)) + vec3(-0.1603) * vec3(color) + vec3(0.2878) - color * vec3(0.9))) * fadeVal);
}

vec3 doWarm(vec3 result){
    vec3 yuvVec = vec3(0.1765, -0.1255, 0.0902);
    vec3 yuvColor = rgbToYuv(result.rgb);
    float luma = yuvColor.r;
    float curveScale = sin(luma * 3.14159);
    float warmth = 1.0;
    yuvColor += 0.375 * warmth * curveScale * yuvVec;
    return yuvToRgb(yuvColor);
}

vec3 highlight(vec4 source, float shadows, float highlights){
    float hsLuminance = dot(source.rgb, luminanceWeighting);
    mediump float shadow = clamp((pow(hsLuminance, 1.0 / shadows) + (-0.76) * pow(hsLuminance, 2.0 / shadows)) - hsLuminance, 0.0, 1.0);
    shadow = shadow * source.a;
    mediump float highlight = clamp((1.0 - (pow(1.0 - hsLuminance, 1.0 / (2.0 - highlights)) + (-0.8) * pow(1.0 - hsLuminance, 2.0 / (2.0 - highlights)))) - hsLuminance, -1.0, 0.0);
    highlight = highlight * source.a;
    mediump vec3 hsresult = vec3(0.0, 0.0, 0.0) + ((hsLuminance + shadow + highlight) - 0.0) * ((source.rgb - vec3(0.0, 0.0, 0.0)) / (hsLuminance - 0.0));
    mediump float contrastedLuminance = ((hsLuminance - 0.5) * 1.5) + 0.5;
    mediump float whiteInterp = contrastedLuminance * contrastedLuminance * contrastedLuminance;
    mediump float whiteTarget = clamp(highlights, 1.0, 2.0) - 1.0;
    hsresult = mix(hsresult, vec3(1.0), whiteInterp * whiteTarget);
    mediump float invContrastedLuminance = 1.0 - contrastedLuminance;
    mediump float blackInterp = invContrastedLuminance * invContrastedLuminance * invContrastedLuminance;
    mediump float blackTarget = 1.0 - clamp(shadows, 0.0, 1.0);
    hsresult = mix(hsresult, vec3(0.0), blackInterp * blackTarget);
    return clamp(hsresult, 0.0, 1.0);
}

void main()
{
    vec4 source = texture2D(inputTexture, textureCoordinate);
    vec3 rst = highlight(source,0.67, 1.75);
    rst = highlight(vec4(rst, source.a), 0.89, 1.75);
    rst = (rst - vec3(0.5)) * 0.904 + vec3(0.5);
    rst = fadeAdjust(rst.rgb, 0.1 * source.a);

    rst = (rst - vec3(0.5)) * 0.94 + vec3(0.5);
    rst = highlight(vec4(rst, source.a), 0.89, 1.75);
    gl_FragColor = vec4(clamp(rst, 0.0, 1.0), 1.0);
}