#version 430 core

in vec2 TexCoord_FS_in;
in vec3 WorldPos_FS_in;
in vec3 Normal_FS_in;

uniform sampler2D tex1;

uniform sampler2D normalMap;
uniform bool hasNormal;

uniform vec3 cameraPositionWS;
uniform vec3 lightPositionWS;
uniform vec3 lightIntensity; // Amb., Diff., and Specular intensity
uniform vec3 ambientColor;
uniform vec3 diffuseColor;
uniform vec3 specularColor;
uniform vec3 diffuseReflectivity; // Diffuse reflectivity
uniform vec3 ambientReflectivity; // Ambient reflectivity
uniform vec3 specularReflectivity; // Specular reflectivity
uniform float shininess; // Specular shininess factor

out vec4 FragColor;

mat3 getTbn()	//source: https://stackoverflow.com/questions/5255806/how-to-calculate-tangent-and-binormal
{
	// compute derivations of the world position
	vec3 p_dx = dFdx(WorldPos_FS_in);
	vec3 p_dy = dFdy(WorldPos_FS_in);
	// compute derivations of the texture coordinate
	vec2 tc_dx = dFdx(TexCoord_FS_in);
	vec2 tc_dy = dFdy(TexCoord_FS_in);
	// compute initial tangent and bi-tangent
	vec3 t = normalize( tc_dy.y * p_dx - tc_dx.y * p_dy );
	vec3 b = normalize( tc_dy.x * p_dx - tc_dx.x * p_dy ); // sign inversion
	// get new tangent from a given mesh normal
	vec3 n = normalize(Normal_FS_in);
	vec3 x = cross(n, t);
	t = cross(x, n);
	t = normalize(t);
	// get updated bi-tangent
	x = cross(b, n);
	b = cross(n, x);
	b = normalize(b);
	mat3 tbn = mat3(t, b, n);
	return tbn;
}

vec3 phong() {
	vec3 currentnormal = Normal_FS_in;
	mat3 tbn = mat3(1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0);	//identity

	if(hasNormal)	//do the same stuff in tangent space
	{
		tbn = transpose(getTbn());
		currentnormal = 2*texture( normalMap, TexCoord_FS_in ).rgb-1;
		
	}

	vec3 N = normalize( currentnormal );
	vec3 L = tbn * normalize( lightPositionWS - WorldPos_FS_in );
	vec3 V = tbn * normalize( cameraPositionWS - WorldPos_FS_in);
	vec3 H = normalize( V + L );
	float diffuseReflection = max( dot(N, L), 0.0 );
	float spec = max(dot(N, H), 0.0 );
	float specularReflection = pow(spec, shininess );

	vec3 ambientLight = ambientColor * ambientReflectivity * lightIntensity.r;
	vec3 diffuseLight = diffuseColor * diffuseReflectivity * lightIntensity.g * diffuseReflection;

	vec3 textureColor = texture( tex1, TexCoord_FS_in ).rgb;
	vec3 specularLight = specularColor * specularReflectivity * lightIntensity.b * specularReflection;

	return (ambientLight + diffuseLight) * textureColor + specularLight;
}

void main() {
	FragColor = vec4( phong() , 0);
}