#version 330 core

out vec4 FragColor;

in vec3 vColor;
in vec3 vNormal;
in vec3 vFragPos;
in vec2 vTex;
in float vDistanceToIsland;
in vec3 vWorldPos;

uniform vec3 lightPos;
uniform vec4 lightColor;
uniform float uTime;

// Simplex noise for color variation
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,
                        0.366025403784439,
                        -0.577350269189626,
                        0.024390243902439);
    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);
}

void main()
{
    vec3 norm = normalize(vNormal);
    vec2 worldXZ = vWorldPos.xz;

    // Depth-based color variation
    // Shallow water (near islands) is lighter/turquoise, deeper water is darker blue
    float depthFactor = smoothstep(5.0, 30.0, vDistanceToIsland);
    
    // Shallow water colors (near islands)
    vec3 shallowColor = vec3(0.15, 0.55, 0.75);  // Light turquoise
    
    // Deep water colors
    vec3 deepColor = vec3(0.0, 0.25, 0.55);      // Dark blue
    
    // OPTIMIZED: Use single noise call instead of 3 (67% less noise calculations)
    float colorNoise = snoise(worldXZ * 0.1 + uTime * 0.012) * 0.5 + 0.5;
    
    // Blend colors based on depth with simplified noise variation
    vec3 waterColor = mix(shallowColor, deepColor, depthFactor);
    
    // Simplified color variation (single calculation)
    waterColor += vec3(0.0, 0.05, 0.08) * colorNoise * 0.25;
    
    // Simplified sediment pattern (reuse the same noise)
    if (vDistanceToIsland < 15.0) {
        float sedimentInfluence = (1.0 - smoothstep(5.0, 15.0, vDistanceToIsland)) * 0.15;
        waterColor += vec3(0.15, 0.12, 0.05) * colorNoise * sedimentInfluence;
    }

    // Lighting
    vec3 lightDir = normalize(lightPos - vFragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    
    // Ambient light
    float ambient = 0.3;
    
    vec3 diffuse = (ambient + diff * 0.7) * waterColor * lightColor.rgb;

    // Specular highlight (stronger in deeper water)
    vec3 viewDir = normalize(-vFragPos);
    vec3 reflDir = reflect(-lightDir, norm);
    float specPower = mix(32.0, 64.0, depthFactor);
    float spec = pow(max(dot(viewDir, reflDir), 0.0), specPower);
    
    vec3 specular = spec * lightColor.rgb * mix(0.3, 0.6, depthFactor);

    vec3 finalColor = diffuse + specular;
    
    // Transparency varies with depth - shallower water is more transparent
    float alpha = mix(0.65, 0.8, depthFactor);

    FragColor = vec4(finalColor, alpha);
}
