if (typeof Mozilla == 'undefined') {
	var Mozilla = {};
}
if (typeof Mozilla.video == 'undefined') {
	Mozilla.video = {};
}

(function() {

	var Color     = Mozilla.util.Color;
	var ColorAnim = YAHOO.util.ColorAnim;
	var Event     = YAHOO.util.Event;

	Mozilla.video.Ambiance = function(video, canvas, element)
	{
		this.video    = video;
		this.canvas   = canvas;
		this.element  = element;
		this.context  = canvas.getContext('2d');
		this.ambiance = false;

		this.blendPeriod = 2.00; // in seconds

		Event.on(this.video, 'play',  this.startAmbiance, this, true);
		Event.on(this.video, 'pause', this.stopAmbiance, this, true);
		Event.on(this.video, 'ended', this.stopAmbiance, this, true);
	}

	var proto = Mozilla.video.Ambiance.prototype;

	proto.stopAmbiance = function()
	{
		this.ambiance = false;
	}

	proto.startAmbiance = function()
	{
		if (this.ambiance) {
			return;
		}

		var that = this;
		setTimeout(function() {
			that.handleTimeout();
		}, 0);

		this.ambiance = true;
	}

	proto.handleTimeout = function()
	{
		if (this.video.paused || this.video.ended) {
			return;
		}

		var color = this.getAverageColor();

		if (this.blendPeriod === 0) {

			// set color immediately ("live")
			this.element.style.backgroundColor = color;

			var that = this;
			setTimeout(function() {
				that.handleTimeout();
			}, 0);

		} else {

			// interplorate color over blendPeriod seconds
			var animation = new ColorAnim(this.element,
				{ backgroundColor: { to: color } },
				this.blendPeriod);

			animation.onComplete.subscribe(function() {
				if (this.ambiance) {
					var that = this;
					setTimeout(function() {
						that.handleTimeout();
					}, 0);
				}
			}, this, true);

			animation.animate();
		}
	}

	proto.pushVideoFrameToCanvas = function()
	{
		// draw the video on the canvas
		this.context.drawImage(
			this.video,
			0,
			0,
			this.canvas.width,
			this.canvas.height
		);
	}

	proto.getCurrentVideoFrame = function()
	{
		this.pushVideoFrameToCanvas();
		return this.context.getImageData(
			0,
			0,
			this.canvas.width,
			this.canvas.height
		);
	}

	proto.getAverageColor = function()
	{
		var frame = this.getCurrentVideoFrame();

		var r = 0;
		var g = 0;
		var b = 0;

		// calculate average color for frame
		for (var i = 0; i < frame.data.length; i += 4) {
			r += frame.data[i];
			g += frame.data[i + 1];
			b += frame.data[i + 2];
		}

		r = Math.ceil(r / (frame.data.length / 4));
		g = Math.ceil(g / (frame.data.length / 4));
		b = Math.ceil(b / (frame.data.length / 4));

		return Color.toHexFromRgb(r, g, b);
	}

	proto.debug = function(s)
	{
		document.getElementById('debug').appendChild(
			document.createTextNode(s)
		);
		document.getElementById('debug').appendChild(
			document.createElement('br')
		);
	}

})();
