#version 330 core
out vec4 FragColor;

in vec3 color;
in vec3 Normal;
in vec3 currentPosition;
in vec2 textCoordinates;
in vec4 FragPosLightSpace;


uniform sampler2D diffuse0;
uniform sampler2D specular0;
uniform sampler2D shadowMap;

uniform vec4 lightColor;
uniform vec3 pointLightPos;
uniform vec3 lightPos;
uniform vec3 camPos;

uniform bool bothLight;
uniform bool useTexture;

vec3 pointLight(){
	vec3 lightVector = pointLightPos - currentPosition;
	float dist = length(lightVector);
	float a = 3.0;
	float b = 0.7;
	float intensity = 1.0f / (a * dist * dist + b * dist + 1.0f);

	// diffuse lighting
	vec3 normal = normalize(Normal);
	vec3 lightDirection = normalize(lightVector);
	float diffuse = max(dot(normal, lightDirection), 0.0f);

	// specular lighting
	float specularLight = 0.50f;
	vec3 viewDirection = normalize(camPos - currentPosition);
	vec3 reflectionDirection = reflect(-lightDirection, normal);
	float specAmount = pow(max(dot(viewDirection, reflectionDirection), 0.0f), 8);
	float specular = specAmount * specularLight;

	return lightColor.rgb * (diffuse * intensity + specular * intensity);
}

//float ShadowCalculation(vec4 fragPosLightSpace, vec3 normal, vec3 lightDir){
//	vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
//	projCoords = projCoords * 0.5 + 0.5;
//
//	// Debug: clamp to [0,1] and visualize z
//	projCoords.xy = clamp(projCoords.xy, 0.0, 1.0);
//	return projCoords.z; // just return depth to see if it's reasonable
//}

float ShadowCalculation(vec4 fragPosLightSpace, vec3 normal, vec3 lightDir){
	vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
	projCoords = projCoords * 0.5 + 0.5;

	if (projCoords.x < 0.0 || projCoords.x > 1.0 || projCoords.y < 0.0 || projCoords.y > 1.0 || projCoords.z < 0.0 || projCoords.z > 1.0)
	return 0.0;

	float bias = max(0.003 * (1.0 - dot(normal, lightDir)), 0.0005);

	float shadow = 0.0;
	vec2 texelSize = 1.0 / vec2(textureSize(shadowMap, 0));

	for (int x = -1; x <= 1; ++x)
	{
		for (int y = -1; y <= 1; ++y)
		{
			float depth = texture(
				shadowMap,
				projCoords.xy + vec2(x,y) * texelSize
			).r;

			shadow += projCoords.z - bias > depth ? 1.0 : 0.0;
		}
	}

	return shadow / 9.0;
}


vec3 directionalLight(vec4 fragPosLightSpace){
//	vec3 ld = vec3(1.0f, 1.0f, 0.0f);
//	vec3 lightDirection = normalize(ld);

	vec3 normal = normalize(Normal);
	vec3 lightDirection = normalize(lightPos);

	//diffuse
	float diffuse = max(dot(normal, lightDirection), 0.0f);

	// specular lighting
	float specularLight = 0.50f;
	vec3 viewDirection = normalize(camPos - currentPosition);
	vec3 reflectionDirection = reflect(-lightDirection, normal);
	float specAmount = pow(max(dot(viewDirection, reflectionDirection), 0.0f), 32);
	float specular = specAmount * specularLight;

//	return lightColor.rgb * (diffuse + specular);


	//shadow
	float shadow = ShadowCalculation(
		fragPosLightSpace,
		normal,
		-lightDirection
	);

	float lighting = (1.0 - shadow) * (diffuse + specular);

	return lightColor.rgb * lighting;

//	return texture(diffuse0, textCoordinates) * (diffuse + ambient + specular) * lightColor;
//	return (texture(diffuse0, textCoordinates) * (diffuse + ambient) + texture(specular0, textCoordinates).r * specular) * lightColor;

}



void main()
{
	//ambient lighting
	float ambient = 0.20f;

	// Use texture or vertex color based on uniform
	vec4 baseColor;

	if (useTexture) {
		baseColor = texture(diffuse0, textCoordinates);
	} else {
		baseColor = vec4(color, 1.0);
	}

	vec3 totalNonAmbientLight;

	if (bothLight){
		totalNonAmbientLight = pointLight() * 20.0f + directionalLight(FragPosLightSpace);
	}else{
		totalNonAmbientLight = directionalLight(FragPosLightSpace);
	}


//	vec3 projCoords = FragPosLightSpace.xyz / FragPosLightSpace.w;
//	projCoords = projCoords * 0.5 + 0.5;
//
//	FragColor = vec4(vec3(projCoords.z), 1.0);
//	return;

	FragColor = baseColor * vec4(ambient + totalNonAmbientLight, 1.0f);

//	FragColor = vec4(1.0, 0.0, 0.0, 1.0);

//	vec3 projCoords = FragPosLightSpace.xyz / FragPosLightSpace.w;
//	projCoords = projCoords * 0.5 + 0.5;
//
//	FragColor = vec4(projCoords.z);
}