#version 330 core
struct Material
{
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shininess;
};

layout (location = 0) out vec4 fragColor;
layout (location = 1) out vec4 brightColor;

in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoord;
in vec4 FragPosLightSpace;
in mat3 tangentMatrix;

uniform vec3 lightDir;
uniform vec3 viewPos;
uniform vec3 lightColor;

uniform sampler2D texDiffuse;
uniform sampler2D texSpecular;
uniform sampler2D texNormal;
uniform sampler2D shadowMap;

uniform Material material;

uniform float alpha;

vec3 projCoords;

float shadowCalc(vec3 coords)
{
    float closestDepth = texture(shadowMap, coords.xy).r;
    float currentDepth = coords.z;

    vec3 normal = normalize(Normal);

    float bias = max(0.000006 * (1.0 - dot(normal, lightDir)), 0.000001);
	bias = 0;

    // PCF
    float shadow = 0.0;
    vec2 texelSize = 1.0 / textureSize(shadowMap, 0);
    for(int x = -2; x <= 2; ++x)
    {
        for(int y = -2; y <= 2; ++y)
        {
            float pcfDepth = texture(shadowMap, coords.xy + vec2(x, y) * texelSize).r;
            shadow += currentDepth - bias > pcfDepth  ? 1.0 : 0.0;
        }    
    }
    shadow /= 25.0;
    
    if(coords.z > 1.0)
        shadow = 0.0;
        
    return shadow;
}

//VSM - Not working
float chebyshevUpperBound(float distancee)
{		
	vec2 moments = texture(shadowMap, projCoords.xy).rg;

	// Surface is fully lit. as the current fragment is before the light occluder
	if (distancee <= moments.x)
		return 1.0;
	
	// The fragment is either in shadow or penumbra. We now use chebyshev's upperBound to check
	// How likely this pixel is to be lit (p_max)
	float variance = moments.y - (moments.x*moments.x);
	variance = max(variance,0.00002);
	
	float d = distancee - moments.x;
	float p_max = variance / (variance + d*d);

	return p_max;
}

void main()
{
    // Ambient
    vec3 ambient = lightColor * material.ambient;
      
    // Diffuse 
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(-lightDir);

    // Apply normal mapping
    norm = texture(texNormal, TexCoord).rgb;
    norm = normalize(norm * 2.0 - 1.0);
    norm = normalize(tangentMatrix * norm);

    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = (diff * material.diffuse) * lightColor;
        
    // Specular
    vec3 viewDir = normalize(viewPos - FragPos);
	
	//blinn-phong
	vec3 halfwayDir = normalize(lightDir + viewDir);
	float spec = pow(max(dot(norm, halfwayDir), 0.0), material.shininess);
    vec3 specular = spec * lightColor * material.specular * vec3(texture(texSpecular, TexCoord));


	// perform perspective divide & transform to [0,1] range
	projCoords = FragPosLightSpace.xyz / FragPosLightSpace.w;
	projCoords = projCoords * 0.5 + 0.5;

	// Calculate Variance Shadow
	//float shadow = chebyshevUpperBound(projCoords.z);
	float shadow = shadowCalc(projCoords);

	//make shadow not POP out like a rapist (sorry for the wording)
	if(projCoords.x>0.95)
		shadow = shadow * ((1-projCoords.x)*20);

	if(projCoords.x<0.05)
		shadow = shadow * projCoords.x*20;

	if(projCoords.y>0.95)
		shadow = shadow * ((1-projCoords.y)*20);

	if(projCoords.y<0.05)
		shadow = shadow * projCoords.y*20;

    vec3 lighting = (ambient + (1-shadow) * (diffuse + specular)) * vec3(texture(texDiffuse, TexCoord));

    //vec3 lighting = (ambient + diffuse + specular) * vec3(texture(texDiffuse, TexCoord));    
    //vec3 result = (ambient + diffuse) * vec3(texture(texDiffuse, TexCoord));
    //result += specular * vec3(texture(texSpecular, TexCoord));

	//final color homogenized
    fragColor = vec4(lighting, alpha);
	//fragColor = vec4(projCoords.x, 0.0, 0.0, 1.0);
	//fragColor = vec4(shadow, 0.0, 0.0, 1.0);
	//draws the depth of the shadowMap relevant for the given fragment
    
    // Render to second color buffer attachment for bloom post processing effect
    // Calculate brightness by converting to grayscale
    float brightness = dot(fragColor.rgb, vec3(0.2126, 0.7152, 0.0722));
    if (brightness > 0.9) brightColor = vec4(fragColor.rgb, 1.0);
    else brightColor = vec4(0.0f, 0.0f, 0.0f, 1.0f);
}
