#version 410 core
layout(location = 0) out vec4 outColor;


struct Light {
	vec3 worldLightPosition;
	vec3 lightColorAmbient;
	vec3 lightColorDiffuse;
	vec3 lightColorSpecular;
	float attenuationConstant;
	float attenuationLinear;
	float attenuationSpecular;
	float shininess;
	float castsShadow;
};

uniform vec3 player_position;

uniform Light light;
uniform sampler2D textureSampler_color;
uniform sampler2D textureSampler_position;
uniform sampler2D textureSampler_normals;
uniform vec2 screen_size;



vec2 near_far = vec2(0.1f, 50.0f);
uniform samplerCubeShadow cubemapSampler_shadow;


// TODO: set/get constants somewhere else
float ka = 0.175f;
float kd = 0.7f;
float ks = 0.6f;

void main(){

	// calculating uvs
	vec2 uv = gl_FragCoord.xy / screen_size;

	vec3 color = texture(textureSampler_color, uv).rgb;
	vec3 object_position = texture(textureSampler_position, uv).xyz;
	vec3 object_normal = texture(textureSampler_normals, uv).xyz;


	// Direction from the point on the surface to the camera
	vec3 object_to_player_direction = player_position - object_position;

	// Direction from the point on the surface to the light
	vec3 object_to_light_direction = light.worldLightPosition - object_position;

	// Distance from the light source to the point on the surface
	float light_to_object_distance = distance(light.worldLightPosition, object_position);

	// calculate the light attenuation
	float attenuation = 1.0 / (light.attenuationConstant + light.attenuationLinear * light_to_object_distance + light.attenuationSpecular * pow(light_to_object_distance, 2));
	


	float currentDistanceToLight = (light_to_object_distance - near_far.x) / (near_far.y - near_far.x);
	currentDistanceToLight = clamp(currentDistanceToLight, 0, 1);

	// sample shadow cube map
	float referenceDistanceToLight = texture(cubemapSampler_shadow, vec4(-normalize(object_to_light_direction), currentDistanceToLight -0.0011));
	
	
	// compare distances to determine whether the fragment is in shadow

// normalize the vectors or strange things will happen
		vec3 n = normalize(object_normal);
		vec3 l = normalize(object_to_light_direction);
		vec3 v = normalize(object_to_player_direction);

		// TODO: maybe not -l
		// calculating the reflection vector
		vec3 r = reflect(-l, n);

		// calculating cos between normal and light | eye and reflection
		float cosTheta = clamp(dot(n, l), 0, 1);
		float cosAlpha = clamp(dot(v, r), 0, 1);

		// do the shading
		vec3 colorRGB = 
						kd * color * light.lightColorDiffuse * cosTheta +
						ks * color * light.lightColorSpecular * pow(cosAlpha, light.shininess);

		// apply light attenuation
colorRGB *= attenuation;		
		colorRGB += ka * color * light.lightColorAmbient;
		colorRGB = clamp(colorRGB, 0, 1);


	if(light.castsShadow > 0.5) {

		outColor = vec4(colorRGB * referenceDistanceToLight, 1);
	}
	else{
		outColor = vec4(colorRGB, 1);
	}
}