/**
 * The main namespace.
 **/
var Vn =
{
	Config: {}
	,jsIncludes: {}
	,cssIncludes: {}
	,xmlIncludes: {}
	,customTags: {}
	,head: document.getElementsByTagName ('head')[0]
	,isMobileCached: null

	,_registerIncludedScripts: function ()
	{
		var scripts = this.head.getElementsByTagName ('script');
		
		var basePath = location.protocol +'//'+ location.host;
		basePath += location.port ? ':'+ location.port : '';
		basePath += location.pathname;
		console.log (basePath);
		
		for (var i = 0; i < scripts.length; i++)
		{
			var path = scripts[i].src.match (/^([\w\./:~-]+)[?#]?.*$/);
		}
	}
	
	/**
	 * Includes a new Javascript in the current document, if the script
	 * is already included, does nothing and calls the callback.
	 *
	 * @param {string} fileName The script file name
	 * @param {Function} callback The function to call when script is
	 * downloaded and included
	 **/
	,includeJs: function (fileName, callback, skipVersion)
	{
		var includeData = this.jsIncludes[fileName];
	
		if (includeData === undefined)
		{
			var src = fileName;

			if (!skipVersion)
				src = src +'?'+ Vn.Cookie.get ('hedera_version');

			var script = document.createElement ('script');
			script.type = 'text/javascript';
			script.async = false;
			script.src = src;

			includeData = {
				 script: script
				,callbacks: []
				,loaded: false
			};
			
			if (callback)
				includeData.callbacks.push (callback);

			script.onload =
				this._jsLoaded.bind (this, includeData, true);
			script.onerror =
				this._jsLoaded.bind (this, includeData, false);
			script.onreadystatechange =
				this._jsStateChanged.bind (this, includeData);

			this.jsIncludes[fileName] = includeData;

	   		this.head.appendChild (script);
		}
		else if (callback)
		{
			if (includeData.loaded)
				callback ();
			else
				includeData.callbacks.push (callback);
		}
	}

	,_jsStateChanged: function (includeData)
	{
		console.log ('js: '+ includeData.script.readyState);

		if (includeData.script.readyState == 'complete')
			this._jsLoaded (includeData, true);
	}

	,_jsLoaded: function (includeData, success)
	{
		if (includeData.loaded)
			return;
	
		for (var i = 0; i < includeData.callbacks.length; i++)
			includeData.callbacks[i] (success);

		includeData.loaded = true;
		includeData.callbacks = null;
	}
	
	/**
	 * Includes an entire Javascript library including it's localized file.
	 *
	 * @param {string} libName The folder of the library
	 * @param {Array<string>} files Array with every library file name
	 **/
	,includeLib: function (libName, files)
	{
		Vn.Locale.loadScript ('js/'+ libName +'.js');

		for (var i = 0; i < files.length; i++)
			this.includeJs ('js/'+ libName +'/'+ files[i] +'.js');
	}
	
	/**
	 * Includes a new CSS stylesheet in the current document, if the stylesheet
	 * is already included, does nothing.
	 *
	 * @param {string} fileName The stylesheet file name
	 **/
	,includeCss: function (fileName)
	{
		var cssData = this.cssIncludes[fileName];

		if (!cssData)
		{
			var link = document.createElement ('link');
			link.rel = 'stylesheet';
			link.type = 'text/css';
			link.href = fileName +'?'+ Vn.Cookie.get ('hedera_version');
			this.head.appendChild (link);
			
			this.cssIncludes[fileName] = 
			{
				 included: true
				,link: link
			};
		}
		else if (!cssData.included)
		{
			cssData.link.disabled = false;
			cssData.included = true;
		}
	}
	
	/**
	 * Excludes a CSS stylesheet from the current document.
	 *
	 * @param {string} fileName The stylesheet file name
	 **/
	,excludeCss: function (fileName)
	{
		var cssData = this.cssIncludes[fileName];
	
		if (cssData && cssData.included)
		{
			cssData.link.disabled = true;
			cssData.included = false;
		}		
	}

	/**
	 * Request an XML file.
	 *
	 * @param {string} path The file path
	 * @param {Function} callback The function to call when file is downloaded
	 **/
	,loadXml: function (path, callback)
	{
		var includeData = this.xmlIncludes[path];
	
		if (true || !includeData)
		{
			var request = new XMLHttpRequest ();
			request.onreadystatechange =
				this._onXmlReady.bind (this, request, path, callback);
			request.open ('get', path +'?'+ Vn.Cookie.get ('hedera_version'), true);
			request.send ();
		}
		else if (callback)
			callback (true);
	}
	
	,_onXmlReady: function (request, path, callback)
	{
		if (request.readyState != 4)
			return;

		if (request.status == 200)
			this.xmlIncludes[path] = request.responseXML;
			
		if (callback)
			callback (request.status == 200);
	}
	
	/**
	 * Gets the DOM object from an included XML file.
	 *
	 * @param {string} path The file path
	 * @return {Object} The DOM object
	 **/
	,getXml: function (path)
	{
		return this.xmlIncludes[path];
	}

	/**
	 * Checks if user is using a mobile browser.
	 *
	 * return {boolean} %true if is mobile, %false otherwise.
	 **/
	,isMobile: function ()
	{
		if (this.isMobileCached === null)
		{
			var regExp = /(Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone)/i;
			this.isMobileCached =  navigator.userAgent.match (regExp);
		}

		return this.isMobileCached;
	}

	,get: function (id)
	{
		return document.getElementById (id);
	}
};

