#version 330 core

uniform sampler2D in_texture;
uniform samplerCube shadow_cubemap;
uniform sampler2D offset_map;
uniform vec4 worldspace_light_position; //worldspace
uniform vec3 light_position; //viewspace light position
uniform vec2 near_far; //near and far plane for cm cams

in  vec4  worldspace_pos;
in  vec3 ex_normal;
in  vec3 ex_eye;
in  vec2 fragment_texcoord;

out vec4 out_color;

const int offset_size = 8;

float calculate_shadow() {
	return 0;
}

void main(void) {

	//soft shadow testing
	vec2 offsets[offset_size + 1];
	offsets[0] = vec2(0,0);
	offsets[1] = vec2(1,0);
	offsets[2] = vec2(0,1);
	offsets[3] = vec2(1,1);
	offsets[4] = vec2(-1.0, 0.0);
	offsets[5] = vec2(0.0, -1.0);
	offsets[6] = vec2(-1.0, -1.0);
	offsets[7] = vec2(1.0, -1.0);
	offsets[8] = vec2(-1.0, 1.0);

	float diffuse_intensity;
	float specular_intensity;

	//calculate vector from surface point to light pos
	//(both in worldspace)
	vec3 cm_lookup_vec = worldspace_pos.xyz - worldspace_light_position.xyz;

	float eps = 0.15; //small offset
	float weight = 0.25;

	//--------------------------
	// accumulate shadow samples
	//--------------------------
	float shadow = 1.0f;
	//do testing samples first
	for (int i=0; i< offset_size + 1; i++) {
		//vec3 offset = texture(offset_map, vec2((i % offset_size), i / offset_size) ).xyz;
		vec3 offset = vec3(offsets[i], 0);
		//vec3 offset = vec3((i % offset_size), (i / offset_size), 0 );
		// read depth val from shadowmap
		vec3 sample_lookup_vec = cm_lookup_vec + offset*weight;
		float smallest_dist_to_light = texture(shadow_cubemap, sample_lookup_vec).r;

		//dist to light for current fragment
		float current_dist_to_light = length(sample_lookup_vec);
		//weight = 0.05 * current_dist_to_light;

		//undo previous [0,1] mapping of lightsource distance
		smallest_dist_to_light *= near_far.y;

		if (smallest_dist_to_light+eps < current_dist_to_light) {
			//fragment lies in shadow
			shadow -= 1.0 / (offset_size + 1);
		}
	}


	//if we are in penumbra, take more samples
	if ((shadow != 1.0) && (shadow > 0.0001) ) {
	//if (true) {

	weight = 0.04;
	shadow = 1.0;
	int offset_size_square = offset_size * offset_size;
	for (int i=0; i< offset_size_square; i++) {
		//vec3 offset = texture(offset_map, vec2((i % offset_size), i / offset_size) ).xyz;
		//vec3 offset = vec3(offsets[i % offset_size], 0);
		vec3 offset = vec3((i % offset_size), (i / offset_size), 0 );
		// read depth val from shadowmap
		vec3 sample_lookup_vec = cm_lookup_vec + offset*weight;
		float smallest_dist_to_light = texture(shadow_cubemap, sample_lookup_vec).r;

		//dist to light for current fragment
		float current_dist_to_light = length(sample_lookup_vec);
		//weight = 0.05 * current_dist_to_light;

		//undo previous [0,1] mapping of lightsource distance
		smallest_dist_to_light *= near_far.y;

		if (smallest_dist_to_light+eps < current_dist_to_light) {
			//fragment lies in shadow
			shadow -= 1.0 / offset_size_square;
		}

	}

	}
	//--------------------------------
	// accumulate shadow samples done
	//--------------------------------

	vec3 light = normalize(-cm_lookup_vec);
	//vec3 light = normalize(light_position - ex_eye);
	vec3 normal = normalize(ex_normal);

	diffuse_intensity = clamp(max( dot(normal, light), 0.0), 0.0, 1.0);

	vec4 texel_color = texture(in_texture, fragment_texcoord);

	out_color = texel_color * 0.05 + //ambient
				texel_color * diffuse_intensity *  clamp(shadow, 0.2, 1.0) +
				texel_color * specular_intensity;
}