let gl;
let program;
let posLoc,
	colorLoc;
let objects = [];
let lastTimestamp;
let viewMatrix;
const {mat4, mat3, vec3} = glMatrix;
let mouseButtonDown = false;
let horizontalVal = 0;
let verticalVal = 0;

function main() {

	// Get canvas and setup WebGL context
	const canvas = document.getElementById("gl-canvas");
	gl = canvas.getContext('webgl2');

	// Configure viewport
	gl.viewport(0,0,canvas.width,canvas.height);
	gl.clearColor(1.0,1.0,1.0,1.0);

	gl.enable(gl.DEPTH_TEST);

	// Init shader program via additional function and bind it
	program = initShaders(gl, "vertex-shader", "fragment-shader");
	gl.useProgram(program);

	// Get locations of shader variables
	posLoc = gl.getAttribLocation(program, "vPosition");
	colorLoc = gl.getAttribLocation(program, "vColor");

	// get location for the vewMatrix
	const viewLoc = gl.getUniformLocation(program, "viewMatrix");

	//get location for the modelMatrix
	const modelLoc = gl.getUniformLocation(program, "modelMatrix");

	// define view matrix
	/*
	viewMatrix = [
		0.1767766922712326, -0.0589255653321743, -0.013334667310118675, 0, 
		0, 0.2357022613286972, -0.006667333655059338, 0, 
		-0.1767766922712326, -0.0589255653321743, -0.013334667310118675, 0, 
		0, 0, -0.8801880478858948, 1
	];
	*/
	
	eye = vec3.fromValues(0, 0.5, 10);
	target = vec3.fromValues(0, 0, 0);
	up = vec3.fromValues(0, 1, 0);

	viewMatrix = mat4.create();
	mat4.lookAt(viewMatrix, eye, target, up);


	//activate uniform for the viewmatrix
	gl.uniformMatrix4fv(viewLoc, false, viewMatrix);

	// Only clear once
	gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

	let island = new Insel();
	objects.push(island);

	let river = new River();
	objects.push(river);

	let tree = new Tree();
	tree.SetModelMatrix([1, 0, 0], [0, 0, 0], [1, 1, 1]);
	objects.push(tree);

	let cloud = new Cloud();
	cloud.SetModelMatrix([-1, 2, 1], [0, 0, 0], [1, 1, 1]);
	objects.push(cloud);

	document.body.addEventListener("keydown", move);
	document.body.addEventListener("mousemove", mouseMoveEvent);
	document.body.addEventListener("mousedown", mouseDownEvent);
	document.body.addEventListener("mouseup", mouseUpEvent);
	
	window.requestAnimationFrame(render);
};

function move(e)
{
	if (false) {
		if (e.keyCode == '87') //w
		{
			eye[2] = eye[2] - 0.5;
			target[2] = target[2] - 0.5;
		} else if (e.keyCode == '83') //s
		{
			eye[2] = eye[2] + 0.5;
			target[2] = target[2] + 0.5;
		} else if (e.keyCode == '65') //a
		{
			eye[0] = eye[0] - 0.5;
			target[0] = target[0] - 0.5;
		} else if (e.keyCode == '68') //d
		{
			eye[0] = eye[0] + 0.5;
			target[0] = target[0] + 0.5;
		}
	}

	if (true) {
		let distance = Math.sqrt((target[0]-eye[0])**2 + (target[2]-eye[2])**2)
		let moveX = ((target[0]-eye[0])/distance)/2;
		let moveZ = ((target[2]-eye[2])/distance)/2;

		if (e.keyCode == "87") { // w
			eye[0] = eye[0] + moveX;
			eye[2] = eye[2] + moveZ;
			target[0] = target[0] + moveX;
			target[2] = target[2] + moveZ;
		} else if (e.keyCode == "65") { // a
			console.log("key not implemented")
		} else if (e.keyCode == "83") { // s
			console.log("key not implemented")
		} else if (e.keyCode == "68") { // d
			console.log("key not implemented")
		}
	}
	
	console.log(eye[0], eye[2]);
	//set the viewMatrix
	const viewLoc = gl.getUniformLocation(program, "viewMatrix");
	mat4.lookAt(viewMatrix, eye, target, up);
	gl.uniformMatrix4fv(viewLoc, false, viewMatrix);
}

function mouseDownEvent(e) {
	if (e.button == 0) {
		mouseButtonDown = true;
	}
}

function mouseUpEvent(e) {
	if (e.button == 0) {
		mouseButtonDown = false;
	}
}

function mouseMoveEvent(e) {
	if (mouseButtonDown) {
		let changeHorizontal = e.movementX * 0.01;
		let changeVertical = -(e.movementY * 0.01);
		let distanceEyeTarget = Math.sqrt((target[0]-eye[0])**2 + (target[1]-eye[1])**2 + (target[2]-eye[2])**2);

		//changeHorizontal = 0.00;
		//changeVertical = 0.01;

		horizontalVal = (horizontalVal + changeHorizontal) % 360;

		verticalVal = verticalVal + changeVertical;
		if (verticalVal > 1) {
			verticalVal = 1;
		} else if (verticalVal < -1) {
			verticalVal = -1;
		}
		

		let sinX = (Math.round(((Math.sin(horizontalVal))*100)))/100;
		let cosY = (Math.round(((Math.cos(verticalVal))*100)))/100;
		let negCosZ = -(Math.round(((Math.cos(horizontalVal))*100)))/100;

		target[0] = sinX * cosY * 10;
		target[1] = verticalVal * 10;
		target[2] = negCosZ * cosY * 10;

		//set the viewMatrix
		const viewLoc = gl.getUniformLocation(program, "viewMatrix");
		mat4.lookAt(viewMatrix, eye, target, up);
		gl.uniformMatrix4fv(viewLoc, false, viewMatrix);
	}
}

function changeView(e) 
{
	//TODO: in Übungen
}

function render(timestamp)
{
	if(lastTimestamp == undefined) 
	{
		lastTimestamp = timestamp;
	}

	const elapsed = timestamp - lastTimestamp;

	for (var i = 0; i < objects.length; i++)
	{
		objects[i].render();
	} 

	window.requestAnimationFrame(render);
}

main();
