#version 120

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

uniform sampler2D textureSampler;
uniform sampler2D normalSampler;
uniform sampler2D 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, 2.0)
#define ORIGINAL_SIZE vec2(2.0, 2.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) {
	//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 * 2);
	float rand = noise(base) * 8;

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

void main() {
	//Figure out which texture we're going to use.
	int rand = randNoise(uv);

	vec2 offset = vec2(mod(rand, 4), int(rand / 4));

	//The wall map is 4x2, so we need to scale by 1/4 x 1/2
	vec2 scalar = 1.0 / TEXTURE_GRIDS;

	//The final position of the texture is the original UV coordinate, then offset by the
	// random texture (see above), and then scaled to fit.
	vec2 position = (fract(uv * ORIGINAL_SIZE) + offset) * scalar;

	//Texture
	vec3 materialColor = texture2D(textureSampler, position).rgb;
	vec3 specularColor = texture2D(specularSampler, position).rgb;
	vec3 normalColor = normalize(texture2D(normalSampler, position).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);
}