#version 330 core 
out vec4 FragColor;

in vec3 FragPos;
in vec3 ourNormal;
in vec2 TexCoord;

uniform mat4 invProjection;         // Inverse projection matrix
uniform mat4 invView;               // Inverse view matrix

uniform sampler2D splat1; // splat
uniform sampler2D texture1; // sand
uniform sampler2D texture2; // grass1
uniform sampler2D texture3; // stone1
uniform sampler2D texture4; // dirt
uniform sampler2D texture5; // road
uniform vec3 sunPos;
uniform vec3 moonPos;
uniform vec3 viewPos;
uniform float daytime; // 1-0-1 night-day-night
uniform vec3 data; // data.x wtime, data.y freq, data.z amp


float linearizeDepth(float depth) {
    float near=0.1f;
    float far=5000.0f;

    float z = depth * 2.0 - 1.0; // NDC
    return 2.0 * near * far / (far + near - z * (far - near));
}
vec3 getWorldPosition(float depth, vec2 uv, bool linearize) {
    float z = linearize ? linearizeDepth(depth) : (depth * 2.0 - 1.0);
    vec4 clipSpace = vec4(uv * 2.0 - 1.0, linearize ? depth : z, 1.0);
    vec4 viewSpace = invProjection * clipSpace;
    viewSpace /= viewSpace.w;
    vec4 worldSpace = invView * viewSpace;
    return worldSpace.xyz;
}



//vec3 applyFog( in vec3  col,  // color of pixel
//               in float t,    // distnace to point
//               in vec3  ro,   // camera position
//               in vec3  rd )  // camera to point vector
//{
//    float fogAmount = (a/b) * exp(-ro.y*b) * (1.0-exp(-t*rd.y*b))/rd.y;
//    vec3  fogColor  = vec3(0.5,0.6,0.7);
//    return mix( col, fogColor, fogAmount );
//}
void main()
{
   //vec3 sunDir   = normalize(sunPos - FragPos);
   //vec3 moonDir   = normalize(moonPos - FragPos);
   //vec3 viewDir    = normalize(viewPos - FragPos);
   //vec3 halfwayDir = normalize(lightDir + viewDir);
   //float spec = pow(max(dot(normal, halfwayDir), 0.0), shininess);
   //vec3 specular = lightColor * spec;

    //colorSample = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);
    vec2 splatUV=TexCoord*.00775; // scale to fit
    splatUV.y=1.0-splatUV.y; // invert side
    splatUV-=.5; // offset splat uv
    vec3 splat=texture(splat1, splatUV).rgb; // 3 channel + black

    // texture scales
   vec3 color1=texture(texture1, TexCoord*.35).rgb; // sand/black
   vec3 color2=texture(texture2, TexCoord*.5).rgb; // greass/green
   vec3 color3=texture(texture3, TexCoord*.25).rgb; // stone/norm.y green
   vec3 color4=texture(texture4, TexCoord*.35).rgb; // dirt red
   vec3 color5=texture(texture5, TexCoord*.5).rgb; // road blue



   //float LOG2E = 1.442695;
   float ambientStrength = 0.27f;
   vec3 sunColor = vec3(1.0f, 0.93f, 0.74f); // luminate color
   vec3 moonColor = vec3(0.38f, 0.5f, 0.5f); // _sky and _moon
   //vec3 objColor = vec3(0.2f, 0.9f, 0.1f); // for sphere color
   vec3 norm=normalize(ourNormal);

    float minsplat=max(splat.r,splat.g);
    minsplat=max(minsplat,splat.b);

    vec3 splatGreen = mix(color2,color3,1.0-norm.y); // grass,stone

    vec3 mix1 = mix(color4,color5,splat.b); // dirt,road

    vec3 mix2 = mix(mix1,splatGreen,splat.g); // dirt or grass

    vec3 splatColor = mix(color1,mix2,minsplat); // na or other

   float sunY=sunPos.y*0.01; // 1000th = normalized?~
   float sunStrength=clamp(sunY,0.0,1.1); // sun brightness
   sunStrength -= data.z; // amp cloud subtract light
   float moonStrength=clamp(1.0-sunStrength,0.0,0.5);
   vec3 blendColor = mix(sunColor,moonColor,0.0-sunStrength); // tone?
   vec3 ambient = ambientStrength * blendColor;

   vec3 sunDir=normalize(sunPos - FragPos);
   float diff=max(dot(norm, sunDir), 0.0);
   vec3 diffuse=diff*sunColor*sunStrength;

   vec3 moonDir=normalize(moonPos - FragPos);
   float diff2=max(dot(norm, moonDir), 0.0);
   vec3 diffuse2=diff2*moonColor*moonStrength;


    // specular
    float specularStrength = 0.2;
    vec3 viewDir = normalize(viewPos - FragPos);
    //vec3 reflectDir = reflect(-sunDir, norm); // lightDir
    //vec3 reflectDir2 = reflect(-moonDir, norm); // lightDir
    vec3 halfwayDir = normalize(sunDir + viewDir); // lightDir
    vec3 halfwayDir2 = normalize(moonDir + viewDir); // lightDir

    //float spec=pow(max(dot(viewDir, reflectDir), 0.0), 32);
    //float spec2=pow(max(dot(viewDir, reflectDir2), 0.0), 32);
    float spec=pow(max(dot(ourNormal, halfwayDir), 0.0), 32);
    float spec2=pow(max(dot(ourNormal, halfwayDir2), 0.0), 32);
    vec3 specular = specularStrength * spec * sunColor;
    vec3 specular2 = specularStrength * spec2 * moonColor;




    float dt=abs(daytime);

    // fog reusing color1-5 new

    float methodA=dt;
    float methodD=(methodA*2);
    float methodE=(methodA*2)-1;

    // day/night water fog colors  blend
    color1 = vec3(0.0,0.1,0.1); // day
    color2 = vec3(0.1,0.26,0.26);
    color3 = vec3(0.1,0.3,0.36); // <<day begin
    //
    color4 = vec3(0.02,0.02,0.02); // night
    color5 = vec3(0.02,0.03,0.05);
    vec3 color6 = vec3(0.01,0.05,0.07);
 
    vec3 ourColor = vec3(mix(color3,color2,methodD));
    ourColor = mix(ourColor,color1,methodE);
    vec3 ourColor2 = vec3(mix(color5,color4,methodD));
    ourColor2 = mix(ourColor2,color6,methodE);
    //vec3 fogColor = vec3(mix(ourColor,ourColor2,dt));


    vec3 P = getWorldPosition(FragPos.z+2, TexCoord, false); // +1 adds dark near view , +1 or +2, 0 makes a line across screen
    float distance = length(P - viewPos);
    float terrainFogDist = 50.0;
    float fogHeight = 25.0;
    vec3 terrainFogBlend = vec3(mix(ourColor,ourColor2,dt)) * (1.0-dt*4);

    float terrainFogFac = distance * terrainFogDist *.001;
    terrainFogFac=clamp(terrainFogFac,0.0,0.1);
    float tFac = clamp(viewPos.y/fogHeight,1.2,1.8); // min max fac
    //float tFac=1.0;
    float fogFac = clamp(distance / terrainFogDist, 0.0, 0.5*tFac);
    float fogDim=1;
    float hdrBrightness=2.0; // 2.0
    float fogOffset=hdrBrightness-((fogFac*.5)+(fogDim*.5));


    float waterSurfaceFac = 0.0f;
    vec3 underwaterColor = vec3(0.2, 0.6, 0.8) * (1.15-dt*1.45); // Tint
    
    splatColor = mix(underwaterColor, splatColor, 1.0 - (waterSurfaceFac * .4 -.25));


    float epsilon = 120.0; // Small threshold for blending
    float terrainFogEps = smoothstep(distance - epsilon, distance + epsilon, terrainFogFac)*.2+.80; // hdr?
    //float terrainFogEps = distance*.01; // hdr?
    splatColor = mix(terrainFogBlend, splatColor, terrainFogEps);
    splatColor = mix(terrainFogBlend, splatColor, terrainFogEps)*tFac*fogOffset;

    //splatColor=vec3(distance,0.0,0.0);
    //splatColor=P;


   //vec3 result=(ambient + ((diffuse + diffuse2) * 0.5)) * ourNormal;
   vec3 result=(ambient + ((diffuse + diffuse2) * 0.5) + ((specular + specular2) * 0.5)) * splatColor;
    //vec3 result=splatGreen;
    //vec3 result=splatColor;
   FragColor = vec4(result, 1.0f);
   // FragColor = vec4(colorSample, 1.0f); // clean
    //FragColor = vec4(TexCoord.x, TexCoord.y, 0.0, 1.0f); // clean
};
