
window.addEventListener ('load', function () {
	var web = new Vn.Web ();
});

Vn.Web = new Class
({
	Extends: Htk.Widget

	,forms: {}
	,activeForm: null
	,activeCss: null
	,requestedForm: null
	,menuShown: false
	,menuOptions: {}
	,choosedOption: null

	,initialize: function ()
	{
		window.onerror = function (message, file, line)
		{
			var error = new Error (message);
			error.fileName = file;
			error.lineNumber = line;

			Htk.Toast.showError (_('InternalError'));
			this.notifyError (error);
		}.bind (this);

		this.loadingCount = 0;
		this.loader = $('loader');
		this.formHolder = $('form-holder');

		Vn.Hash.initialize ();
		this.hash = Vn.Hash;

		this.hashParam = new Vn.HashParam ({key: 'form'});
		this.hashParam.on ('changed', this.onFormChange, this);

		$('background').onclick = function () {};

		$('menu-button').addEventListener ('click', function (event)
		{
			event.stopPropagation ();

			if (!this.menuShown)
				this.showMenu ();
			else
				this.hideMenu ();
		}.bind (this));

		$('menu-box').addEventListener ('click', function (event)
		{
			event.stopPropagation ();
		});
		
		if (!Vn.Cookie.check ('hedera_cookies'))
		{
			Vn.Cookie.set ('hedera_cookies', true);
			Htk.Toast.showWarning (_('CookiesNotification'));
		}

		this.conn = new Db.Conn ();
		this.conn.on ('error', this.onConnError, this);
		this.conn.on ('loading-changed', this.onConnLoading, this);
//		this.conn.open (null, null, null, this.connOpened.bind (this));

		var sql = 'SELECT default_form, image_dir FROM config;'
			+'SELECT production_domain, test_domain FROM config;'
			+'SELECT name FROM customer_view;'
			+'CALL form_list ();';
		this.conn.execQuery (sql, this.onMainQueryDone.bind (this));
	}

	,showBackground: function ()
	{
		Vn.Node.show ($('background'));
	}

	,hideBackground: function ()
	{
		Vn.Node.hide ($('background'));
	}

	,showMenu: function ()
	{
		this.showBackground ();
		Vn.Node.show ($('menu-box'));
		this.menuShown = true;

		this.hideMenuCallback = this.hideMenu.bind (this);
		document.addEventListener ('click', this.hideMenuCallback);
	}

	,hideMenu: function ()
	{
		this.hideBackground ();
		Vn.Node.hide ($('menu-box'));
		$('menu-button').style.display = 'initial';
		this.menuShown = false;
		
		document.removeEventListener ('click', this.hideMenuCallback);
		this.hideMenuCallback = null;
	}

	,onMainQueryDone: function (resultSet)
	{
		// Retrieving configuration parameters

		var res = resultSet.fetchResult ();
		var columns = res.columns;
	
		if (res.next ())
		for (var i = 0; i < res.columns.length; i++)
			Vn.Config[columns[i].name] = res.get (columns[i].name);

		// Retrieving configuration parameters

		var res = resultSet.fetchResult ();

		if (res.next () && res.get ('test_domain'))
		{
			if (location.host != res.get ('production_domain'))
			{
				var linkText = 'ReturnToOldWebsite';
				var linkField = 'production_domain';
			}
			else
			{
				var linkText = 'TestTheNewWebsite';
				var linkField = 'test_domain';
			}
			
			Vn.Node.setText ($('test-link'), _(linkText));
			$('test-link').href = '//'+ res.get (linkField);
		}
		else
			Vn.Node.hide ($('test-link'));

		// Retrieving the user name

		var userName = resultSet.fetchValue ();

		if (userName)
		{
			var span = $('user-name');
			span.appendChild (document.createTextNode (', '+ userName));
		}

		// Retrieving menu sections		

		var res = resultSet.fetchResult ();	
		var sectionMap = {};
		
		if (res)
		for (var i = 0; res.next (); i++)
		{
			var parent = res.get ('parent');
			
			if (!sectionMap[parent])
				sectionMap[parent] = [];
				
			sectionMap[parent].push (i);
		}

		this.createMenu (res, sectionMap, null, $('menu'));

		// Loading the default form

		this.onFormChange ();
	}
	
	,notifyError: function (error)
	{
		if (error instanceof Error)
		{
			var httpRequest = new Vn.HttpRequest ()
			httpRequest.add
			({
				 'file': error.fileName
				,'line': error.lineNumber
				,'message': error.message
				,'stack': error.stack
			});
			httpRequest.send ('log.php');
		}
	}

	,errorHandler: function (error)
	{
		if (error instanceof Vn.Error)
		switch (error.domain)
		{
			case 'Auth':
				this.unload ();
				location.assign ('?page=login#!error='+ error.code);
				break;
			case 'Version':
				this.newVersion (error);
				break;
			case 'User':
				Htk.Toast.showError (error.message);
				break;
			default:
				console.error (error.message);
				Htk.Toast.showError (_('InternalError'));
		}
		else
		{
			console.error (error);
			Htk.Toast.showError (_('InternalError'));
			this.notifyError (error);
		}
	}

	,onConnError: function (conn, error)
	{
		this.errorHandler (error);
	}

	,onConnLoading: function (conn, isLoading)
	{
		if (isLoading)
			this.loaderPush ();
		else
			this.loaderPop ();
	}
	
	,loaderPush: function ()
	{
		this.loadingCount++;

		if (this.loadingCount == 1)
			this.loader.style.visibility = 'visible';
	}
	
	,loaderPop: function ()
	{
		if (this.loadingCount == 0)
			return;
		
		this.loadingCount--;
		
		if (this.loadingCount == 0)
			this.loader.style.visibility = 'hidden';
	}
	
	,newVersion: function (error)
	{
		if (this.newVersionBlock || this.skipVersion)
			return;
			
		this.newVersionBlock = true;

		var reload;
		var message = _('NewVersionAvailable') +"\n\n"+ error.message;

		if (error.code == 'criticalVersion')
		{
			alert (message)
			reload = true;
		}
		else
		{
			reload = confirm (message);
			this.skipVersion = true;
		}

		if (reload)
		{
			this.unload ();
			location.reload ();
		}
			
		this.newVersionBlock = false;
	}

	,createMenu: function (res, sectionMap, parent, ul)
	{
		var sections = sectionMap[parent];

		for (var i = 0; i < sections.length; i++)
		{
			res.row = sections[i];
		
			var li = document.createElement ('li');
			ul.appendChild (li);

			var a = document.createElement ('a');
			a.href = Vn.Hash.make ({'form': res.get ('path')});
			this.menuOptions[res.get ('path')] = a;
			li.appendChild (a);

			var text = document.createTextNode (_(res.get ('description')));
			a.appendChild (text);
			
			var formId = res.get ('id');
			
			if (sectionMap[formId])
			{
				var submenu = document.createElement ('ul');
				submenu.className = 'submenu';
				li.appendChild (submenu);

				li.addEventListener ('mouseover',
					this.onLiMouseHover.bind (this, submenu, a));
				li.addEventListener ('mouseout',
					this.onLiMouseOut.bind (this));

				this.createMenu (res, sectionMap, formId, submenu);
			}
		}
	}

	,onLiMouseHover: function (submenu, parent)
	{
		if (Vn.isMobile ())
			return;

		this.hideSubmenu ();
		this.activeSubmenu = submenu;

		var rect = parent.getBoundingClientRect ();
		submenu.style.display = 'inline';
		submenu.style.left = rect.right +'px';
		submenu.style.top = rect.top +'px';
	}
	
	,onLiMouseOut: function ()
	{
		this.timeout = setTimeout (this.hideSubmenu.bind (this), 160);
	}
	
	,hideSubmenu: function ()
	{
		var submenu = this.activeSubmenu;
	
		if (submenu)
		{
			submenu.style.display = 'none';
			clearTimeout (this.timeout);
			this.activeSubmenu = null;
			this.timeout = 0;
		}
	}
	
	,onFormChange: function ()
	{
		var formPath = this.hashParam.value;
		this.openForm (formPath ? formPath : Vn.Config['default_form'], null);
	}

	,openForm: function (formPath, callback)
	{
		if (Vn.isMobile ())
			this.hideMenu ();

		this.loaderPush ();

		this.requestedForm = formPath;

		var formInfo = this.forms[formPath];
		var path = 'forms/'+ formPath;

		if (this.activeForm)
		{
			this.activeForm.close ();
			this.activeForm.unref ();
			this.activeForm = null;
		}

		if (this.activeCss)
		{
			Vn.excludeCss (this.activeCss +'/style.css');
			
			if (Vn.isMobile ())
				Vn.excludeCss (this.activeCss  +'/mobile.css');
		}

		this.activeCss = path;

		Vn.includeCss (this.activeCss +'/style.css');
		
		if (Vn.isMobile ())
			Vn.includeCss (this.activeCss +'/mobile.css');

		if (!formInfo)
		{
			var aux = formPath.split ('/');
			var formName = aux[aux.length - 1];

			var klass = 'Vn.'+ formName.charAt (0).toUpperCase ();
			klass += formName.substr (1).replace (/\w\-\w/g, function (token)
			{
				return token.charAt (0) + token.charAt (2).toUpperCase ();
			});

			formInfo = {
				 path: formPath
				,klass: klass
				,localeReady: false
				,jsReady: false
				,uiReady: false
				,error: false
				,ready: false
				,callbacks: []
			};

			Vn.Locale.load (path,
				this.onFormLocaleReady.bind (this, formInfo));
			Vn.includeJs (path +'/'+ formName +'.js',
				this.onFormJsReady.bind (this, formInfo));
			Vn.loadXml ('forms/'+ formPath +'/ui.xml',
				this.onFormUiReady.bind (this, formInfo));

			this.forms[formPath] = formInfo;
		}

		var newChoosedOption = this.menuOptions[formInfo.path];
		
		if (newChoosedOption)
		{
			if (this.choosedOption)
				this.choosedOption.className = null;
			
			newChoosedOption.className = 'selected';
			this.choosedOption = newChoosedOption;
		}

		if (callback)
			formInfo.callbacks.push (callback);
		if (formInfo.ready)
			this.onFormReady (formInfo);
	}

	,onFormLocaleReady: function (formInfo, success)
	{
		formInfo.localeReady = true;
		this.onFormReady (formInfo);
	}

	,onFormJsReady: function (formInfo, success)
	{
		formInfo.jsReady = true;
		formInfo.error = !success;
		this.onFormReady (formInfo);
	}
	
	,onFormUiReady: function (formInfo, success)
	{
		formInfo.uiReady = true;
		formInfo.error = !success;
		this.onFormReady (formInfo);
	}

	,onFormReady: function (formInfo)
	{
		if (!(formInfo.localeReady && formInfo.jsReady && formInfo.uiReady))
			return;

		formInfo.ready = true;

		if (!formInfo.error)
		{
			if (formInfo.path == this.requestedForm)
			try {
				var klass = eval (formInfo.klass);
				this.activeForm = new klass (this, formInfo);
				this.activeForm.open ();
				this.activeForm.activate ();
			}
			catch (e) {
				formInfo.error = true;
				this.errorHandler (error);
			}
		}
		else
			Htk.Toast.showError (_('ErrorLoadingForm'));

		var callbacks = formInfo.callbacks;
		formInfo.callbacks = [];

		for (var i = 0; i < callbacks.length; i++)	
			callbacks[i] (this.activeForm);

		this.loaderPop ();
	}		

	,unload: function ()
	{
		this.hashParam.unref ();
		this.conn.disconnect ('error', this.onConnError, this);
		this.conn.disconnect ('loading-changed', this.onConnLoading, this);
	}
});

