#version 120

// Include support for texture arrays.
#extension GL_EXT_texture_array : require

varying vec2 uv;
varying vec3 light_vector;
varying vec3 eye_vector;
varying vec3 vert_position;
varying vec3 normal_vector;

uniform sampler2DArray textureSampler;
uniform sampler2DArray normalSampler;
uniform sampler2DArray specularSampler;
uniform samplerCube skyboxSampler;

uniform vec4 ambient_color;
uniform vec3 sun_direction;
uniform vec4 sun_color;
uniform float sun_power;
uniform int specular_exponent;
uniform vec3 camera_position;
uniform mat4 inverse_model_mat;
uniform vec3 model_position;
uniform float reflectivity;
uniform vec2 textureScale;
uniform mat4 skybox_mat;

#define TEXTURE_GRIDS vec2(4.0, 1.0)
#define ORIGINAL_SIZE vec2(4.0, 4.0)

//Stupid simple noise
float noise(vec2 co) {
    return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453);
}

int randNoise(vec2 uv, int max) {
	//This is done by taking the floored UV (integer component) and running it through the
	//	above noise function. This value is then multiplied by the number of grids to get a
	// grid offset within the texture.
	vec2 base = floor(uv * textureScale);
	float rand = noise(base) * max;

	int irand = int(floor(rand));
	irand = int(mod(irand, max));
	return irand;
}

void main() {
	vec2 scaled_uv = uv * textureScale;

	//Figure out which texture we're going to use.
	// Calculate 3D textureArray position
	// note that 3 needs to be a uniform as that's the amount in the array.
	int slice = randNoise(uv, 3);
	vec3 array_uv = vec3(scaled_uv, slice);
	
	//Texture
	vec3 materialColor = texture2DArray(textureSampler, array_uv).rgb;
	vec3 specularColor = texture2DArray(specularSampler, array_uv).rgb;
	vec3 normalColor = normalize(texture2DArray(normalSampler, array_uv).rgb * 2.0 - 1.0);

	vec3 n = normalize(normalColor);
	vec3 l = normalize(light_vector);

	//Cosine of the angle from the light to the normal
	float cosTheta = clamp(dot(n, l), 0, 0.6);
	float cosNtheta = 1;
//	if (cosTheta == 0)
		cosNtheta = clamp(dot(-n, l), 0.5, 1.0) + 0.3;

	//Normalized eye vector
	vec3 eye = normalize(eye_vector);

	//Direction of the light reflection
	vec3 reflection = reflect(-l, n);

	//Angle from the eye vector and reflect vector
	float cosAlpha = clamp(dot(eye, reflection), 0, 1.0);

	gl_FragColor = vec4(materialColor * (sun_color.rgb * sun_color.a), 1);

	//Bump mapping
	gl_FragColor *= cosTheta;

	//Ambient color
	gl_FragColor += vec4(materialColor * ambient_color.rgb * cosNtheta, 1);

	vec3 normal_model = normalize(reflect(-normal_vector, n));

	vec3 I = normalize(vert_position - camera_position);
	vec3 R = reflect(I, normalize(normal_model));

	vec3 skyboxR = mat3(skybox_mat) * R;

	vec4 reflectionColor = textureCube(skyboxSampler, skyboxR);

	gl_FragColor = mix(gl_FragColor, reflectionColor, reflectivity);

	//Specular highlights
	gl_FragColor += vec4(specularColor * (sun_color.rgb * sun_color.a) * pow(cosAlpha, specular_exponent), 1);

	// gl_FragColor = reflectionColor;

	// gl_FragColor = vec4((normal_model + 1) / 2, 1);

	// gl_FragColor = vec4((normal_vector + 1) / 2, 1);

	// gl_FragColor = vec4(R, 1);

	// gl_FragColor = vec4(cosTheta);

	// gl_FragColor = vec4(eye_vector, 1);

	//gl_FragColor = vec4(1, 0, 1, 1);

	// gl_FragColor = vec4(fract(uv * 2), 0, 1);
	// gl_FragColor = vec4(mod(rand, 4) / 4, floor(rand / 4) / 2, 0, 1);
	// gl_FragColor = vec4(position, 0, 1);
}