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

require ('./gui.css');

/**
 * The main screen component. It has a left menu, a navbar with configurable
 * action buttons and the body where @Form childs can be displayed.
 */
module.exports = new Class
({
	Extends: Vn.Component,
	Properties:
	{
		/**
		 * The main connection object.
		 */
		conn:
		{
			type: Db.Connection
			,set: function (x)
			{
				this.link ({_conn: x}, {'loading-changed': this._onConnLoadChange });
			}
			,get: function ()
			{
				return this._conn;
			}
		},
		/**
		 * The current open form.
		 */
		activeForm:
		{
			type: Form
			,get: function ()
			{
				return this._activeForm;
			}
		}
	}

	,_forms: {}
	,_activeForm: null
	,_requestedForm: null
	,_menuShown: false
	,_menuOptions: {}
	,_choosedOption: null
	,_shown: false
	,_scrollTimeout: null
	,_navbarVisible: true

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

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

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

		this.$.leftPanel.addEventListener ('click', function (event)
		{
			event.stopPropagation ();
		});

		this.parent (props);

		this.$.socialBar.conn = this._conn;

		var sql = 'SELECT name FROM customer_user;'
			+'SELECT default_form, image_dir, image_host FROM config;'
			+'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.$.formHolder);
		
		if (Vn.isMobile ())
		{
			this._onScrollHandler = this._onScroll.bind (this);
			window.addEventListener ('scroll', this._onScrollHandler);
		}

		this.formParam = new Vn.Param ({
			lot: this.hash,
			name: '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'));
		}
	}
	
	,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.emit ('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.$.userName, userName);

		// Retrieving configuration parameters

		Object.assign (Vn.Config, resultSet.fetchObject ());

		// Retrieving configuration parameters

		var row = resultSet.fetchObject ();

		if (row && row.test_domain)
		{
			if (location.host != row.production_domain)
			{
				var linkText = 'ReturnToOldWebsite';
				var linkField = 'production_domain';
			}
			else
			{
				var linkText = 'TestTheNewWebsite';
				var linkField = 'test_domain';
			}
			
			Vn.Node.setText (this.$.testLink, _(linkText));
			this.$.testLink.href = '//'+ row[linkField];
		}
		else
			Vn.Node.hide (this.$.testLink);

		// Loading the default form

		this._onFormChange ();
	}
	
	,loadMenu: function ()
	{
		var sql = 'CALL formList ()';
		this._conn.execQuery (sql, this._onMenuLoad.bind (this));
	}

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

		var row;
		var res = resultSet.fetchResult ();	
		var sectionMap = {};
		
		if (res)
		for (var i = 0; row = res.fetchObject (); i++)
		{
			var parent = row.parent;
			
			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];

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

			var a = this.createElement ('a');
			a.className = 'clickable';
			
			if (row.path)
			{
				a.href = this.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;
		}
	}

	,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 = window.pageYOffset;
		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;
		}

		var formInfo = this._forms[formPath];

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

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

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

		this._activeForm = new formInfo.klass ({
			gui: this,
			formInfo: formInfo
		});
		this._activeForm.open ();
	}
	
	,setForm: function (form)
	{
		Vn.Node.removeChilds (this.$.formHolder);

		if (form)
		{
			var div = this.createElement('div');
			div.appendChild (form);

			this.$.formHolder.appendChild (div);
			setTimeout (this._onSetFormTimeout.bind (this), 10);
		}
	}
	
	,_onSetFormTimeout: function ()
	{
		Vn.Node.addClass (this.$.formHolder.firstChild, 'slide');
	}
	
	,setTitle: function (title)
	{
		Vn.Node.setChild (this.$.title, title);
	}
	
	,setActions: function (actions)
	{
		Vn.Node.setChild (this.$.actionBar, actions);
	}
	
	,closeForm: function ()
	{
		if (this._activeForm)
		{
			this._activeForm.formInfo.unload ();
			this._activeForm.close ();
			this._activeForm.unref ();
			this._activeForm = null;
		}

		if (this._choosedOption)
		{
			Vn.Node.removeClass (this._choosedOption, 'selected');
			this._choosedOption = null;
		}
	}

	,openReport: function (reportName, params)
	{
		var hashParams = {
			form: 'preview',
			report: reportName
		};
		this.hash.params = Object.assign (hashParams, params);
	}

	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Supplant

	,supplantUser: function (user, callback)
	{
		this._conn.supplantUser (user,
			this._onUserSupplant.bind (this, callback));
	}
	
	,_onUserSupplant: function (callback, supplantOk)
	{
		if (!supplantOk)
			return;
	
		this.loadMenu ();
	
		var sql = 'SELECT name FROM customer_user';
		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 ();
		this.loadMenu ();
		this._onFormChange ();
	}
	
	//++++++++++++++++++++++++++++++++++++++++++++++++++++++ Destroy

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

