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

require('./gui.css');

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.myUser;'
			+'SELECT defaultForm FROM config;'
			+'SELECT url FROM imageConfig;'
			+'SELECT dbproduccion FROM vn2008.tblContadores;'
			+'SELECT productionDomain, testDomain 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('testDomain')) {
			if (location.host != res.get('productionDomain')) {
				var linkText = 'Old website';
				var linkField = 'productionDomain';
			} else {
				var linkText = 'Test the new website';
				var linkField = 'testDomain';
			}
			
			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.defaultForm;
		
		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)	
			return Htk.Toast.showError(_('Error loading form'));
		if (!this._shown)
			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.myUser';
		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();
	}
});