/**
 *  Grass layer object
 */

/* Constructor */
// Sets up a new grass layer.

function GrassLayer(name, phaseOffset) {
	this.phaseOffset = phaseOffset;
	
	// Create a grass layer element.
	this.layer = document.createElement('div');
	this.layer.className = 'layer';
	
	// Add ten 'blocks' of grass to the layer.
	for(var n = 0; n < 10; n++) {
		this.layer.appendChild(document.createElement('span'));
	}
	
	// Create a grass container element.
	this.container = document.createElement('div');
	this.container.className = 'grass ' + name;
	this.container.appendChild(this.layer);
	
	// Start the layer's animation.
	this.wave();
	
	return this;
}

/* Wave */
// Runs the wave animation.

GrassLayer.prototype.wave = function() {
	var self = this;
	var oneStep = (Math.PI * 2) / 2000;
	
	// Start the wave animation.
	setInterval(function() {
		var currentStep = (new Date().getTime() + self.phaseOffset) % 2000;
		self.layer.style.left = Math.round(Math.sin(oneStep * currentStep) * 3) - 410 + 'px';
	}, 10);
}

/* Start grass */
// Initializes all grass layers.

function startGrass() {

	// Add three grass containers to the page.
	document.body.appendChild(new GrassLayer('back', 500).container);
	document.body.appendChild(new GrassLayer('center', 1250).container);
	document.body.appendChild(new GrassLayer('front', 0).container);
}

/**
 *  Letter object
 */

/* Constructor */
// Sets up a new letter.

function Letter(name, animationDelay) {
	this.name = name;
	this.animationDelay = animationDelay;
	
	// Create a letter element.
	this.letter = document.createElement('div');
	this.letter.className = 'letter ' + name;
	
	// Start the letter's animation.
	this.hover();
	
	return this;
}

/* Hover */
// Runs the hover animation.

Letter.prototype.hover = function() {
	var self = this;
	var phaseOffset = (this.animationDelay == null ? 1100 : 2000) - (new Date().getTime() % 2000) - (this.animationDelay || 0);
	var oneStep = (Math.PI * 2) / 2000;
	
	// Set up the letter's onclick handler.
	this.letter.onclick = function() {
		self.animationDelay = null;
		
		if(self.animationHandler) {
			clearTimeout(self.animationHandler);
		}
		
		self.letter.onclick = null;
		self.fall();
	}
	
	// Start the hover animation.
	this.animationHandler = setTimeout(function() {
		self.animationHandler = setInterval(function() {
			var currentStep = (new Date().getTime() + phaseOffset) % 2000;
			self.letter.style.top = Math.round(Math.sin(oneStep * currentStep) * 5) + 'px';
		}, 10);
	}, this.animationDelay || 0);
}

/* Fall */
// Runs the fall animation.

Letter.prototype.fall = function() {
	var self = this;
	var floorHeight = this.name == 'driehoog' ? 144 : 179;
	var fallingHeight = floorHeight - this.letter.offsetTop;
	var animationStart = new Date().getTime();
	var animationEnd = animationStart + 250;
	var phaseOffset = 250 - (animationStart % 250);
	var oneStep = (Math.PI / 2) / 250;
	
	// Start the fall animation.
	this.animationHandler = setInterval(function() {
		var now = new Date().getTime();
		
		// If not yet finished, continue the animation...
		if(now < animationEnd) {
			var currentStep = (new Date().getTime() + phaseOffset) % 250;
			self.letter.style.top = Math.round(Math.cos(Math.PI + (oneStep * currentStep)) * fallingHeight) + fallingHeight + 'px';
		}
		
		// ...or proceed to the bounce animation.
		else {
			clearInterval(self.animationHandler);
			self.letter.style.top = floorHeight + 'px';
			self.bounce();
		}
	}, 10);
}

/* Bounce */
// Runs the bounce animation.

Letter.prototype.bounce = function() {
	var self = this;
	var floorHeight = this.name == 'driehoog' ? 144 : 179;
	var animationStart = new Date().getTime();
	var animationEnd = animationStart + 250;
	var phaseOffset = 250 - (animationStart % 250);
	var oneStep = Math.PI / 250;
	
	// Start the bounce animation.
	this.animationHandler = setInterval(function() {
		var now = new Date().getTime();
		
		// If not yet finished, continue the animation...
		if(now < animationEnd) {
			var currentStep = (new Date().getTime() + phaseOffset) % 250;
			self.letter.style.top = Math.round(Math.sin(Math.PI + (oneStep * currentStep)) * 5) + floorHeight + 'px';
		}
		
		// ...or finish up and set the letter's onclick handler.
		else {
			clearInterval(self.animationHandler);
			self.letter.style.top = floorHeight + 'px';
			self.letter.onclick = function() {
				self.letter.onclick = null;
				self.floatUp();
			}
		}
	}, 10);
}

/* Float up */
// Runs the float up animation.

Letter.prototype.floatUp = function() {
	var self = this;
	var floatHeight = this.name == 'driehoog' ? 144 : 179;
	var animationStart = new Date().getTime();
	var animationEnd = animationStart + 2500;
	var phaseOffset = 2500 - (animationStart % 2500);
	var oneHorizontalStep = (Math.PI * 4) / 2500;
	var oneVerticalStep = (Math.PI / 2) / 2500;
	
	// Start the float up animation.
	this.animationHandler = setInterval(function() {
		var now = new Date().getTime();
		
		// If not yet finished, continue the animation...
		if(now < animationEnd) {
			var currentStep = (new Date().getTime() + phaseOffset) % 2500;
			self.letter.style.left = Math.round(Math.sin(oneHorizontalStep * currentStep) * 5) + 'px';
			self.letter.style.top = Math.round(Math.cos(oneVerticalStep * currentStep) * floatHeight) + 'px';
		}
		
		// ...or proceed to the hover animation.
		else {
			clearInterval(self.animationHandler);
			self.hover();
		}
	}, 10);
}

/* Start letters */
// Initializes all letters.

function startLetters() {

	// Create a reference to the header element.
	var header = document.getElementsByTagName('h1')[0];
	
	// Add all letters to the header.
	header.appendChild(new Letter('driehoogvoor', 1250).letter);
	header.appendChild(new Letter('driehoogvoo', 500).letter);
	header.appendChild(new Letter('driehoogvo', 0).letter);
	header.appendChild(new Letter('driehoogv', 1750).letter);
	header.appendChild(new Letter('driehoog', 1000).letter);
	header.appendChild(new Letter('driehoo', 250).letter);
	header.appendChild(new Letter('drieho', 1250).letter);
	header.appendChild(new Letter('drieh', 750).letter);
	header.appendChild(new Letter('drie', 0).letter);
	header.appendChild(new Letter('dri', 1250).letter);
	header.appendChild(new Letter('dr', 500).letter);
	header.appendChild(new Letter('d', 1750).letter);
	
	header.className = 'alive';
}

/**
 *  Initializer
 */

window.onload = function() {
	startGrass();
	startLetters();
}

