/**
 * @author Lukas Goldschmidt
 * @projectDescription  A 3D Interface to Wikipeda,
 showcasing HTML5, WebGL, Three.js, JQuery-UI andseveral APIs.
 * @fileOverview A 3D Interface to Wikipeda,
 showcasing HTML5, WebGL, Three.js, JQuery-UI andseveral APIs.
 * @name wiki_browser
 * @version     0.1
 */

/**
 * @namespace LG
 * @desc Namespace of Lukas Goldschmidt
 */

/**
 * @namespace LG.wb
 * @desc Namespace of Wikipedia 3D Browser 2011
 */

/**
 * Holds all Classes  of Wikipedia 3D Browser 2011
 * @namespace LG.wb.Class
 */
Namespace.Manager.Register("LG.wb.Class");

/*
 * @namespace LG.wb.App
 * @desc Holds all Instances of Classes in the Wikipedia 3D Browser 2011
 */
Namespace.Manager.Register("LG.wb.App");

LG.wb.Class.Browser = new Class(/** @lends LG.wb.Class.Browser.prototype */
{
	/** a maximum value for elements */
	maxele : 10,
	/** a maximum value for x position */
	maxx : 950,
	/** a maximum value for y position */
	miny : -950,

	/** initial value for x position */
	ini_xpos : -850,
	/** initial value for y position */
	ini_ypos : 850,
	/** initial value for z position */
	ini_zpos : 0,

	xpos : -850,
	ypos : 850,
	zpos : 0,

	xdis : 410,
	ydis : 410,
	zdis : 500,

	/** object to hold our item instances */
	items : {},
	/** array for clickable items */
	click_items : [],

	/**
	 * @class LG.wb.Class.Browser
	 * The Main Object containing the central logic framework .
	 * @member LG.wb.Class.Browser
	 * @param {Object} ele
	 * @param {int} width
	 * @param {int} height
	 * @constructs LG.wb.Class.Browser
	 */
	initialize : function(ele, width, height) {
		this.width = width;
		this.height = height;
		// Update proportions
		this.resized();

		this.isShiftDown = false;

		this.alurl = 'http://access.alchemyapi.com/calls/url/URLGetRankedNamedEntities';
		this.wpurl = 'http://' + DEF_LANG + '.wikipedia.org/w/api.php';
		this.projector = new THREE.Projector();
		this.renderer = new THREE.CanvasRenderer();
		var that = this;

		this.renderer.setSize(this.width, this.height);

		ele.innerHTML = "";
		ele.appendChild(this.renderer.domElement);

		this.resized();
		this.renderer.domElement.onMouseOver = "self.focus()";
		this.renderer.domElement.onMouseOut = function() {
			$("#ac").focus();
		};

		ele.onBlur = function() {
			LG.wb.App.Browser.camera.isShiftDown = false;
		};

		this.ctarget = new LG.THREE.Object3D();
		this.ctarget.position.x = 0;
		this.ctarget.position.y = 0;
		this.ctarget.position.z = 0;

		//		this.camera = new LG.FirstPersonCamera({
		this.camera = new LG.THREE.FirstPersonCamera({
			fov : 33,
			aspect : this.width / this.height,
			near : 1,
			far : 30000,
			target : this.ctarget,
			lookSpeed : 1.8,
			movementSpeed : 220,
			noFly : true,
			activeLook : false,
			domElemnt : that,
			verticalMin : Math.PI * 0.35,
			verticalMax : Math.PI * 0.65
		});
		this.camera.Browser = this;

		// this.camera.position.z = 1900;
		this.camera.position.x = 300;
		this.camera.position.y = -40;
		this.camera.position.y = 340;
		this.camera.constrainVertical = true;

		this.scene = new THREE.Scene();
		this.ray = new THREE.Ray(this.camera.position, null)

		this.pointLight = new THREE.PointLight(0xFFFFFF);
		this.pointLight.position.x = 300;
		this.pointLight.position.y = 1000;
		this.pointLight.position.z = 630;
		this.scene.addLight(this.pointLight);

		var r = "images/cube/plain_sky_1/";
		this.texture_placeholder = document.createElement( 'canvas' );
		this.texture_placeholder.width = 128;
		this.texture_placeholder.height = 128;

		var context = this.texture_placeholder.getContext( '2d' );
		context.fillStyle = 'rgb( 200, 200, 200 )';
		context.fillRect( 0, 0, this.texture_placeholder.width, this.texture_placeholder.height );

		var materials = [

			this.loadTexture( r + 'px.jpg' ), // right 2
			this.loadTexture( r + 'nx.jpg' ), // left 4
			this.loadTexture( r + 'py.jpg' ), // top 5
			this.loadTexture( r + 'ny.jpg' ), // bottom 6
			this.loadTexture( r + 'pz.jpg' ), // back 1
			this.loadTexture( r + 'nz.jpg' )  // front 3

		];

		mesh = new THREE.Mesh( new THREE.CubeGeometry( 10000, 10000, 10000, 7, 7, 7, materials, true ), new THREE.MeshFaceMaterial() );
		mesh.overdraw = true;
		this.scene.addObject( mesh);
		// grid
		plane = new THREE.Mesh(new THREE.PlaneGeometry(2200, 2200, 20, 20), new THREE.MeshBasicMaterial({
			color : 0x339933,
			wireframe : true
		}));
		plane.rotation.x = -90 * Math.PI / 180;
		plane.position.y = -170;
		this.scene.addObject(plane);

		$("#ac").focus();

		// open something or not ??
		if(DEF_WPAGE !== '') {
			this.load(DEF_WPAGE);
		}

	},
	resized : function() {
		var c = $("canvas:last");
		this.offset = c.offset();
		$("#dialog-message").dialog.height = window.innerHeight;
	},
	render : function() {
		for(index in this.items) {
			this.items[index].animate();
		}
		this.renderer.render(this.scene, this.camera);
	},
	animate : function() {
		requestAnimationFrame(LG.wb.App.Browser.animate);
		LG.wb.App.Browser.render();
	},
	reset : function() {
		//alert('reset pushed');
		var tmp = this.items;
		// remove from scene
		for(index in this.items) {
			this.scene.removeChild(this.items[index].model);
			this.items[index].model = null;
			this.items[index] = null;

		}
		// empty array
		this.items = {};
		this.click_items = [];

		this.xpos = this.ini_xpos;
		this.ypos = this.ini_ypos;
		this.zpos = this.ini_zpos;
		$("#ac").val('');
		this.render();
		$("#ac").focus();

	},
	/**
	 * Show some text
	 */
	showText : function(item) {
		var Browser = this;
		$("#dialog-message").html(item.text);

		$("#dialog-message a[href^='\/wiki\/']").each(function() {

			var wpage = this.href.substr(this.href.lastIndexOf("/") + 1);
			this.onClick = 'LG.wb.App.Browser.load("' + wpage + '")';
			this.href = 'javascript:LG.wb.App.Browser.load("' + wpage + '");';
		});
		$("#dialog-message a[href^='\/w\/']").each(function() {
			this.href = '#';
		}).css('color', '#333333');
		$("#dialog-message a[href^='http']").each(function() {

			this.target = '_blank';
			this.onClick = 'javascript: $("#dialog-message").dialog("open");';

		});
		//height : window.innerHeight,
		$("#dialog-message").dialog("option", "height", window.innerHeight)

		$("#dialog-message").dialog("option", "title", item.wpage)
		$("#dialog-message").dialog('open');
		LG.wb.App.Browser.dialogOpen = true;

	},
	loadTexture : function(path) {

		var texture = new THREE.Texture(this.texture_placeholder), material = new THREE.MeshBasicMaterial({
			map : texture
		}), image = new Image();

		image.onload = function() {

			texture.needsUpdate = true;
			material.map.image = this;

			this.render();

		};

		image.src = path;

		return material;

	},
	load : function(wpage) {

		// take a wiki page and initialize an Item Object
		$("#ac").val('');
		$("#ac").blur();

		var s = str_clean(wpage);
		if(this.items[s] !== undefined)
			return;
		// item exists, bye

		this.items[s] = new LG.wb.Class.Item(this, wpage);
		// add geometry to scene
		this.scene.addObject(this.items[s].model);

		this.click_items = this.click_items.concat(this.items[s].click_items);
		//		this.click_items.push(this.items[s].Label1);

		this.items[s].goTo(this.xpos, this.ypos, this.zpos);

		//	this.ctarget.position(new THREE.Vector3(this.xpos, this.ypos, this.zpos));
		this.camera.target.position.x = this.xpos;
		this.camera.target.position.y = this.zpos;
		this.camera.target.position.z = this.ypos;
		//	this.camera.position.x = this.xpos + 300;
		//	this.camera.position.y = this.zpos + 100;
		//	this.camera.position.z = this.ypos + 100;
		// advance position
		this.xpos += this.xdis;
		if(this.xpos > this.maxx) {
			this.xpos = this.ini_xpos;
			this.ypos -= this.ydis;
		}
		if(this.ypos < this.miny) {
			this.xpos = this.ini_xpos;
			this.ypos = this.ini_ypos;
			this.zpos += this.zdis;
		}

	},
});
// End of LG.wb.Class.Browser

include('js/wb_item.js');

// Callbacks

var ac_callback = function(data) {
	// part of the wikipedia Site restriction workaround
	$('#ac').autocomplete('option', 'source', data[1]);
}
// Helper
function str_clean(str) {
	// make function name out of wiki page
	return 'f_' + str.replace(/\W|\s/gi, "_");
}

// user resized window
function resizeUpdate() {
	LG.wb.App.Browser.resized();

};

var resizeTimer;
$(window).resize(function() {
	clearTimeout(resizeTimer);
	resizeTimer = setTimeout(resizeUpdate, 100);
});
/* Execution starts here */
$(document).ready(function() {
	/**
	 * The object acts as a hub, and vontainer for items and such
	 */
	LG.wb.App.Browser = new LG.wb.Class.Browser(document.getElementById('content'), 960, 480);

	//	LG.wb.App.Browser.wpurl = 'http://de.wikipedia.org/w/api.php';

	//	LG.wb.App.Browser.display('The_Beatles');
	//	LG.wb.App.Browser.display('Bob_Marley');
	//	LG.wb.App.Browser.display('Barack_Obama');
	//	LG.wb.App.Browser.display('Star_Trek');
	//	LG.wb.App.Browser.display('Stargate_Atlantis');

	LG.wb.App.Browser.animate();

	$("#ac").autocomplete({
		source : function(request, response) {
			url = LG.wb.App.Browser.wpurl + "?action=opensearch&search=" + this.value + "&format=json&callback=ac_callback   ";
			var elem = document.createElement('script');
			elem.setAttribute('src', url);
			elem.setAttribute('type', 'text/javascript');
			document.getElementsByTagName ('head')[0].appendChild(elem);
			response([]);

		},
		search : function(event, ui) {
			//url: 'http://en.wikipedia.org/w/api.php?action=opensearch',
			url = LG.wb.App.Browser.wpurl + "?action=opensearch&search=" + this.value + "&format=json&callback=ac_callback   ";

			var elem = document.createElement('script');
			elem.setAttribute('src', url);
			elem.setAttribute('type', 'text/javascript');
			document.getElementsByTagName ('head')[0].appendChild(elem);
			return true;
		},
		//		autoFocus:true,
		minLength : 2,
		position : {
			my : "left bottom",
			at : "left top"
		},
		select : function(event, ui) {
			LG.wb.App.Browser.load(ui.item.label);
			LG.wb.App.Browser.renderer.domElement.focus();
		}
	});
	$("#ac").click().focus();
	$("#dialog-message").dialog({
		maxHeight : window.innerHeight,
		draggable : true,
		minWidth : 800,
		autoOpen : false,
		modal : false,
		close : function(event, ui) {
			LG.wb.App.Browser.dialogOpen = false;
		},
		buttons : {
			Ok : function() {
				$(this).dialog("close");
			},
		}
	});
	$("#dialog-about").dialog({
		minWidth : 480,
		autoOpen : false,
		modal : true,
		close : function(event, ui) {
			LG.wb.App.Browser.dialogOpen = false;
		},
		buttons : {
			Ok : function() {
				$(this).dialog("close");
			}
		}
	});

	//
	$("#about").button({
		//	text:false,
		icons : {
			primary : "ui-icon-help"
		}
	}).click(function() {
		LG.wb.App.Browser.dialogOpen = true;
		$("#dialog-about").dialog('open');

	});

	$("#reset").button({
		//	text: false,
		icons : {
			primary : "ui-icon-document"
		}
	}).click(function() {
		LG.wb.App.Browser.reset();

	});
	var options = $("#langsel");
	LG.wb.App.Browser.wp_languages = wp_languages;

	$.each(LG.wb.App.Browser.wp_languages, function() {
		if(this.lang == DEF_LANG) {
			options.append($("<option selected />").val(this.url).text(this.lang));
		} else {
			options.append($("<option />").val(this.url).text(this.lang));
		}
	});
	options.change(function() {
		LG.wb.App.Browser.wpurl = $("#langsel option:selected").val() + 'w/api.php';
	});

	$("#tabs").tabs();

});

google.load('search', '1');
