#version 410 core
 
// layout(location = 0) states, that out should go to
// standard back-buffer (usually and only if it's bound!)
// In theory, we could render into multiple buffers at
// the same time. Thus we have to specify the target.
layout(location = 0) out vec4 outColor;

uniform sampler2D texture_diffuse1;
uniform sampler2D texture_specular1;

uniform int numLights;

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

uniform Light lights[8];

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

in vec2 texCoord;
in vec3 cameraNormal;
in vec3 cameraEyeDir;
in vec3 cameraLightDir[8];
in float attenuation[8];
in vec3 normal_vec;

void main(){

	// get material colors
	vec3 materialDiffuseColor = texture(texture_diffuse1, texCoord).rgb;
	vec3 materialSpecularColor = clamp(2.0f * texture(texture_diffuse1, texCoord).rgb, vec3(0,0,0), vec3(1,1,1));// TODO: texture(texture_specular1, texCoord).rgb;
	vec3 materialAmbientColor = materialDiffuseColor   * vec3(1.0, 0.97, 0.85);

	vec3 outColorRGB = vec3(0, 0, 0);
	for(int i = 0; i < numLights; i++){

		// normalize the vectors or strange things will happen
		vec3 n = normalize(cameraNormal);
		vec3 l = normalize(cameraLightDir[i]);
		vec3 e = normalize(cameraEyeDir);

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

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

		// do the shading
		vec3 color = ka * materialAmbientColor * lights[i].lightColorAmbient +
					 kd * materialDiffuseColor * lights[i].lightColorDiffuse * cosTheta +
					 ks * materialSpecularColor * lights[i].lightColorSpecular * pow(cosAlpha, lights[i].shininess);

		// apply light attenuation
		color *= attenuation[i];

		// accumulate the color
		outColorRGB += color;
	}

//	vec3 moss_col = vec3(0.3f, 1.0f, 1.0f);
	vec3 path_col = vec3(0.6f, 0.3f, 0.15f);

	float angle_to_z = 0.5f * ( 1 + dot(normalize(normal_vec), vec3(0.0f,0.0f,1.0f)));
	float path_coeff = angle_to_z * pow(angle_to_z, 2);
//	float moss_coeff = pow(angle_to_z, 8);

	// add alpha channel

	outColor = vec4(outColorRGB * (1-path_coeff) + ((outColorRGB.r + outColorRGB.g + outColorRGB.b) / 3.0f) * path_col * path_coeff, 1);
//	outColor = vec4(outColor.rgb * (1-moss_coeff) + clamp(moss_col *moss_coeff * 2.5, vec3(0,0,0) * 0.7, vec3(1,1,1)), 1);

}