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

require('./gui.scss');

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.$.leftPanel.addEventListener('click', function(event) {
			event.stopPropagation();
		});

		this.parent(props);

		var sql = 'SELECT id, name, nickname FROM account.myUser;'
			+'SELECT defaultForm FROM config;'
			+'SELECT url FROM imageConfig;'
			+'SELECT dbproduccion FROM vn.config;'
			+'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.$.formHolder);
		
		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

		this.user = resultSet.fetchObject();
		Vn.Node.setText(this.$.userName, this.user.nickname);

		// 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.$.devInfo.style.display = 'block';
			this.$.version.textContent = Vn.Cookie.get('vnVersion');
		}

		// Retrieving configuration parameters

		var res = resultSet.fetchObject();

		if (res && res.testDomain) {
			if (location.host != res.productionDomain) {
				var linkText = 'Old website';
				var linkField = 'productionDomain';
			} else {
				var linkText = 'Test the new website';
				var linkField = 'testDomain';
			}
			
			Vn.Node.setText(this.$.testLink, _(linkText));
			this.$.testLink.href = '//'+ res.get(linkField);
			this.$.testLink.style.display = 'block';
		} else
			this.$.testLink.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.fetchData();	
		var sectionMap = {};
		let i = 0;

		for (const row of res) {
			var parent = row.parentFk;
			
			if (!sectionMap[parent])
				sectionMap[parent] = [];
				
			sectionMap[parent].push(i++);
		}

		Vn.Node.removeChilds(this.$.mainMenu);
		this.createMenu(res, sectionMap, null, this.$.mainMenu);
	}

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

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

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

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

			a.appendChild(text);
			li.appendChild(a);
			
			var formId = row.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;
		}
	}

	,onMenuClick(event) {
		event.stopPropagation();
		this.showMenu();
	}

	,showMenu: function() {
		this.showBackground();
		Vn.Node.addClass(this.$.leftPanel, '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.$.leftPanel, '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.$.topBar;
		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.$.formHolder);

		if (form) {
			this.$.formHolder.appendChild(form);
			setTimeout(this._onSetFormTimeout.bind(this), 0);
		}
	}
	
	,_onSetFormTimeout: function() {
		Vn.Node.addClass(this.$.formHolder, 'show');
	}
	
	,setTitle: function(title) {
		Vn.Node.removeChilds(this.$.title);
	
		if (title)
			this.$.title.appendChild(title);
	}
	
	,setActions: function(actions) {
		Vn.Node.removeChilds(this.$.actionBar);
				
		if (actions)
			this.$.actionBar.appendChild(actions);
	}
	
	,closeForm: function() {
		if (this.activeForm) {
			Vn.Node.removeClass(this.$.formHolder, '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, err) {
		if (err) throw err;
	
		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);
		this.$.supplant.classList.toggle('show', true);
	}

	,onSupplantExitClick: function() {
		this.$.supplant.classList.toggle('show', false);
		this._conn.supplantEnd();
		sessionStorage.removeItem('supplantUser',
			sessionStorage.getItem('supplantUser'));
		this.loadMenu();
		this._onFormChange();
	}
	
	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Destroy

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