var Module = require ('./module');
var Css = require ('./gui.css');
var Tpl = require ('./gui.xml');

module.exports = new Class
({
	Extends: Htk.Component,
	Properties:
	{
		conn:
		{
			type: Db.Connection
			,set: function (x)
			{
				this.link ({_conn: x}, {'loading-changed': this._onConnLoadChange });
			}
			,get: function ()
			{
				return this._conn;
			}
		}
	}

	,forms: {}
	,activeForm: null
	,activeCss: null
	,requestedForm: null
	,menuShown: false
	,menuOptions: {}
	,choosedOption: null
	,_shown: false
	,_scrollTimeout: null
	,_navbarVisible: true

	,initialize: function (props)
	{
		this.builderInitString (Tpl);
		this.loadingCount = 0;

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

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

		this.$('left-panel').addEventListener ('click', function (event)
		{
			event.stopPropagation ();
		});

		this.parent (props);

		this.$('social-bar').conn = this._conn;

		var sql = 'SELECT nickname FROM account.userView;'
			+'SELECT default_form FROM config;'
			+'SELECT url FROM imageConfig;'
			+'SELECT dbproduccion FROM vn2008.tblContadores;'
			+'SELECT production_domain, test_domain FROM config;';
		this._conn.execQuery (sql, this.onMainQueryDone.bind (this));

		this.loadMenu ();
	}
	
	,show: function ()
	{
		if (this._shown)
			return;
	
		this._shown = true;
		this.doc.body.appendChild (this.node);
		Htk.Toast.pushTop (this.$('form-holder'));
		
		if (Vn.isMobile ())
		{
			this._onScrollHandler = this._onScroll.bind (this);
			window.addEventListener ('scroll', this._onScrollHandler );
		}

		this.hash = Vn.Hash;
		this.formParam = new Vn.HashParam ({key: 'form'});
		this.formParam.on ('changed', this._onFormChange, this);
		
		if (!localStorage.getItem ('hederaCookies'))
		{
			localStorage.setItem ('hederaCookies', true);
			Htk.Toast.showWarning (_('By using this site you accept cookies'));
		}

		this.supplantInit ();
	}
	
	,hide: function ()
	{
		if (!this._shown)
			return;
	
		this._shown = false;

		if (Vn.isMobile ())
			window.removeEventListener ('scroll', this._onScrollHandler);

		Htk.Toast.popTop ();
		this.formParam.unref ();
		this.closeForm ();
		this.hideMenu ();
		Vn.Node.remove (this.node);
	}
	
	,logout: function ()
	{
		this.onLogoutClick ();
	}
	
	,onLogoutClick: function ()
	{
		this._conn.close (this._onConnClose.bind (this));
	}
	
	,_onConnClose: function ()
	{
		this.signalEmit ('logout');
	}

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

	,onMainQueryDone: function (resultSet)
	{
		// Retrieving the user name

		var userName = resultSet.fetchValue ();
		Vn.Node.setText (this.$('user-name'), userName);

		// 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

		Vn.Config.imageUrl = resultSet.fetchValue ();

		// Retrieving configuration parameters

		var isTesting = !resultSet.fetchValue ();

		if (isTesting)
		{
			this.$('dev-info').style.display = 'block';
			this.$('version').textContent = Vn.Cookie.get ('vnVersion');
		}

		// Retrieving configuration parameters

		var res = resultSet.fetchResult ();

		if (res.next () && res.get ('test_domain'))
		{
			if (location.host != res.get ('production_domain'))
			{
				var linkText = 'Old website';
				var linkField = 'production_domain';
			}
			else
			{
				var linkText = 'Test the new website';
				var linkField = 'test_domain';
			}
			
			Vn.Node.setText (this.$('test-link'), _(linkText));
			this.$('test-link').href = '//'+ res.get (linkField);
			this.$('test-link').style.display = 'block';
		}
		else
			this.$('test-link').style.display = 'none';

		// Loading the default form

		this._onFormChange ();
	}
	
	,loadMenu: function ()
	{
		var sql = 'SELECT * FROM myMenu';
		this._conn.execQuery (sql, this._onMenuLoad.bind (this));
	}

	,_onMenuLoad: function (resultSet)
	{
		// Retrieving menu sections		

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

		Vn.Node.removeChilds (this.$('main-menu'));
		this.createMenu (res, sectionMap, null, this.$('main-menu'));
	}

	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Menu

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

		for (var i = 0; i < sections.length; i++)
		{
			res.row = sections[i];
		
			var li = this.createElement ('li');
			ul.appendChild (li);
	
			var text = this.createTextNode (_(res.get ('description')));

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

			a.appendChild (text);
			li.appendChild (a);
			
			var formId = res.get ('id');
			
			if (sectionMap[formId])
			{
				var submenu = this.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 (this.menuShown)
			return;

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

		var rect = parent.getBoundingClientRect ();
		Vn.Node.addClass (submenu, 'popup');
		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)
		{
			Vn.Node.removeClass (submenu, 'popup');
			submenu.style.left = '';
			submenu.style.top = '';
			clearTimeout (this.timeout);
			this.activeSubmenu = null;
			this.timeout = 0;
		}
	}

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

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

	,hideMenu: function ()
	{
		if (!this.menuShown)
			return;
	
		this.hideBackground ();
		Vn.Node.removeClass (this.$('left-panel'), 'show');
		this.menuShown = false;
		
		this.doc.removeEventListener ('click', this.hideMenuCallback);
		this.hideMenuCallback = null;
	}

	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Navigation bar
	
	,_onScroll: function ()
	{
		if (this._scrollTimeout === null)
			this._scrollTimeout = setTimeout (
				this._scrollTimeoutFunc.bind (this), 150);
	}
	
	,_scrollTimeoutFunc: function ()
	{
		if (!this._shown)
			return;
		
		var navbar = this.$('top-bar');
		var yOffset = Vn.Browser.getPageYOffset ();
		var showNavbar = this._lastYOffset > yOffset || yOffset < navbar.offsetHeight;
		
		if (showNavbar !== this._navbarVisible)
		{
			if (showNavbar)
				var translateY = 0;
			else
				var translateY = -navbar.offsetHeight;

			navbar.style.transform =
				'translateZ(0) translateY('+ translateY +'px)';
		}
		
		this._navbarVisible = showNavbar;
		this._lastYOffset = yOffset;
		this._scrollTimeout = null;
	}

	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Background

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

	,hideBackground: function ()
	{
		Vn.Node.removeClass (this.$('background'), 'show');
	}

	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Spinner
	
	,loaderPush: function ()
	{
		this.loadingCount++;

		if (this.loadingCount == 1)
			this.$('loader').start ();
	}
	
	,loaderPop: function ()
	{
		if (this.loadingCount == 0)
			return;
		
		this.loadingCount--;
		
		if (this.loadingCount == 0)
			this.$('loader').stop ();
	}
	
	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Forms
	
	,_onFormChange: function ()
	{
		var formPath = this.formParam.value;
		
		if (!formPath)
			formPath = Vn.Config['default_form'];
		
		this.openForm (formPath,
			this._onFormLoad.bind (this));
	}

	,openForm: function (formPath, callback)
	{
		this.hideMenu ();
		this.loaderPush ();
		
		this.closeForm ();
		this.requestedForm = formPath;

		var newChoosedOption = this.menuOptions[formPath];
		
		if (newChoosedOption)
		{
			Vn.Node.addClass (newChoosedOption, 'selected');
			this.choosedOption = newChoosedOption;
		}

		this.activeCss = 'forms/'+ formPath +'/style.css';
		Vn.includeCss (this.activeCss);

		var formInfo = this.forms[formPath];

		if (!formInfo)
		{
			formInfo = new Module ('forms', formPath);
			this.forms[formPath] = formInfo;
		}
		
		formInfo.addCallback (callback);
	}

	,_onFormLoad: function (formInfo)
	{
		this.loaderPop ();

		if (formInfo.error)
		{	
			Htk.Toast.showError (_('Error loading form'));
			return;
		}

		this.activeForm = new formInfo.klass (this, formInfo);
		this.activeForm.open ();
	}
	
	,setForm: function (form)
	{
		Vn.Node.removeChilds (this.$('form-holder'));

		if (form)
		{
			this.$('form-holder').appendChild (form);
			setTimeout (this._onSetFormTimeout.bind (this), 0);
		}
	}
	
	,_onSetFormTimeout: function ()
	{
		Vn.Node.addClass (this.$('form-holder'), 'show');
	}
	
	,setTitle: function (title)
	{
		Vn.Node.removeChilds (this.$('title'));
	
		if (title)
			this.$('title').appendChild (title);
	}
	
	,setActions: function (actions)
	{
		Vn.Node.removeChilds (this.$('action-bar'));
				
		if (actions)
			this.$('action-bar').appendChild (actions);
	}
	
	,closeForm: function ()
	{
		if (this.activeForm)
		{
			Vn.Node.removeClass (this.$('form-holder'), 'show');
			this.activeForm.close ();
			this.activeForm.unref ();
			this.activeForm = null;
		}

		if (this.activeCss)
		{
			Vn.excludeCss (this.activeCss);
			this.activeCss = null;
		}

		if (this.choosedOption)
		{
			Vn.Node.removeClass (this.choosedOption, 'selected');
			this.choosedOption = null;
		}
	}
	
	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Reports
	
	,openReport: function (reportName, batch)
	{
		this.loaderPush ();

		var module = new Module ('reports', reportName);
		module.addCallback (this._onReportLoad.bind (this, batch));
	}
	
	,_onReportLoad: function (batch, module)
	{
		this.loaderPop ();

		if (module.error)
		{
			Htk.Toast.showError (_('Error loading report'));
			return;
		}
		
		var report = new module.klass (module, this);
		report.open (batch);
	}
	
	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Supplant
	
	,supplantInit: function ()
	{
		var user = sessionStorage.getItem ('supplantUser');

		if (user != null)
			this.supplantUser (user);
	}

	,supplantUser: function (user, callback)
	{
		this._conn.supplantUser (user,
			this._onUserSupplant.bind (this, callback, user));
	}
	
	,_onUserSupplant: function (callback, user, supplantOk)
	{
		if (!supplantOk)
			return;
	
		sessionStorage.setItem ('supplantUser', user);
		this.loadMenu ();
	
		var sql = 'SELECT nickname FROM account.userView';
		this._conn.execQuery (sql, this._onSupplantName.bind (this));
		
		if (callback)
			callback ();
	}

	,_onSupplantName: function (resultSet)
	{
		var userName = resultSet.fetchValue ();
		Vn.Node.setText (this.$('supplanted'), userName);
		Vn.Node.show (this.$('supplant'));
	}

	,onSupplantExitClick: function ()
	{
		Vn.Node.hide (this.$('supplant'));
		this._conn.supplantEnd ();
		sessionStorage.removeItem ('supplantUser',
			sessionStorage.getItem ('supplantUser'));
		this.loadMenu ();
		this._onFormChange ();
	}
	
	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Destroy

	,_destroy: function ()
	{
		this.hide ();
		this.parent ();
	}
});