#version 330 core

out vec4 FragColor;
in vec2 TexCoord;

uniform sampler2D InputTexture;
uniform float highlightsValue; // -100 to 100
uniform float shadowsValue;    // -100 to 100

// More accurate perceptual luminance (Rec. 709)
float luminance(vec3 color) {
    return dot(color, vec3(0.2126, 0.7152, 0.0722));
}

// Smoothstep with better performance than quintic
float smootherStep(float edge0, float edge1, float x) {
    float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
    return t * t * (3.0 - 2.0 * t);
}

vec3 applyHighlightsShadows(vec3 color) {
    float lum = luminance(color);
    
    // Define threshold values similar to Lightroom
    float shadowThreshold = 0.3;
    float highlightThreshold = 0.7;
    
    // Calculate adjustment weights with smoother falloff
    float shadowWeight = 1.0 - smootherStep(0.0, shadowThreshold * 2.0, lum);
    float highlightWeight = smootherStep(highlightThreshold, 1.0, lum);
    
    // Calculate adaptive adjustment factors
    float shadowFactor = shadowsValue > 0.0 ? 
        mix(1.0, 1.0 + (shadowsValue / 100.0), shadowWeight) :
        mix(1.0, 1.0 + (shadowsValue / 150.0), shadowWeight);
        
    float highlightFactor = highlightsValue > 0.0 ?
        mix(1.0, 1.0 - (highlightsValue / 150.0), highlightWeight) :
        mix(1.0, 1.0 - (highlightsValue / 100.0), highlightWeight);
    
    // Apply adjustments while preserving colors
    vec3 adjusted = color * shadowFactor * highlightFactor;
    
    // Preserve some saturation characteristics like Lightroom
    float newLum = luminance(adjusted);
    float saturationFactor = 1.0;
    
    // Boost saturation slightly when lifting shadows (like Lightroom)
    // if (shadowsValue > 0.0 && lum < shadowThreshold) {
    //     saturationFactor = 1.0 + (shadowsValue / 300.0) * (1.0 - lum / shadowThreshold);
    // }
    
    // Reduce saturation slightly when recovering highlights (like Lightroom)
    if (highlightsValue > 0.0 && lum > highlightThreshold) {
        saturationFactor *= 1.0 - (highlightsValue / 400.0) * ((lum - highlightThreshold) / (1.0 - highlightThreshold));
    }
    
    // Apply saturation adjustment while preserving luminance
    return mix(vec3(newLum), adjusted, saturationFactor);
}

void main() {
    vec4 color = texture(InputTexture, TexCoord);
    color.rgb = applyHighlightsShadows(color.rgb);
    FragColor = vec4(clamp(color.rgb, 0.0, 1.0), color.a);
}