
var Login = require ('./login');
var Gui = require ('./gui');

module.exports = new Class
({
	Extends: Vn.Object,
	Properties:
	{
		conn:
		{
			type: Db.Connection
			,get: function ()
			{
				return this._conn;
			}
		}
	}

	,initialize: function ()
	{
		window.onerror = this._onWindowError.bind (this);
		window.onunload = this._onWindowUnload.bind (this);
		Vn.Hash.initialize ();

		this._isGuest = new Vn.HashParam
		({
			type: Boolean,
			key: 'guest'
		});
		this._isGuest.on ('changed', this._onGuestChange, this);

		var conn = new Db.Connection ();
		this.link ({_conn: conn}, {'error': this._onConnError});
	}
	
	,run: function ()
	{
		var guest = localStorage.getItem ('hederaGuest');
		
		if (guest)
			localStorage.removeItem ('hederaGuest');
	
		if (localStorage.getItem ('vnToken'))
		{
			this._conn.open (null, null, null,
				this._onAutoLogin.bind (this));
		}
		else if (this._isGuest.value || guest)
		{
			this._guestLogin ();
		}
		else
		{
			var login = this._login = new Login ({conn: this._conn});
			login.on ('login', this._onLogin, this);
			login.show ();
		}
	}
	
	,_onGuestChange: function ()
	{
		if (this._isGuest.value)
			this._guestLogin ();
	}
	
	,_guestLogin: function ()
	{
		this._conn.open (
			null,
			null,
			null,
			this._onGuestLogin.bind (this),
			true
		);
	}
	
	,_onGuestLogin: function (conn, success)
	{
		this._isGuest.value = undefined;

		if (success)
		{
			localStorage.setItem ('hederaGuest', true);
			this._onLogin ();
		}
		else
			this.run ();
	}
	
	,_onAutoLogin: function (success)
	{
		if (!success)
			this.run ();
		else
			this._onLogin ();
	}
	
	,_onLogin: function ()
	{
		this._freeLogin ();
		
		var gui = this._gui = new Gui ({conn: this._conn});
		gui.on ('logout', this._onLogout, this);
		gui.show ();
	}
	
	,_onLogout: function (gui)
	{
		this._freeGui ();
		localStorage.removeItem ('hederaGuest');
		this.run ();
	}
	
	,_onWindowUnload: function ()
	{
		this.unref ();
	}
	
	,_onWindowError: function (message, file, line)
	{
		var error = new Error (message);
		error.fileName = file;
		error.lineNumber = line;
		this._notifyError (error);
	}

	,_onConnError: function (conn, error)
	{
		if (error instanceof Vn.JsonException)
		{
			if (error.exception)
				var exception = error.exception
					.replace (/\\/g, '.')
					.replace (/Exception$/, '')
					.replace (/^Vn\.Web\./, '');
			else
				var exception = null;
		
			switch (exception)
			{
				case 'BadLogin':
					Htk.Toast.showError (_('Invalid login'));
					this._logout ();
					break;
				case 'SessionExpired':
					Htk.Toast.showError (_('You\'ve been too idle'));
					this._logout ();
					break;
				case 'OutdatedVersion':
					this._newVersion (error);
					break;
				default:
					Htk.Toast.showError (error.message);
			}
		}
		else
		{
			console.error (error);
			this._notifyError (error);
		}
	}
	
	,_logout: function ()
	{
		if (this._gui)
			this._gui.logout ();
	}
	
	,_newVersion: function (error)
	{
		if (this.skipVersion)
			return;

		this.skipVersion = true;

		if (confirm (_('New version available')))
			location.reload ();
	}
	
	,_notifyError: function (error)
	{
		Htk.Toast.showError (_('There was an internal error'));

		var params = {
			 'file': error.fileName
			,'line': error.lineNumber
			,'message': error.message
			,'stack': error.stack
		};
		this._conn.send ('core/log', params);
	}
	
	,_freeLogin: function ()
	{
		if (this._login)
		{
			this._login.disconnectByInstance (this);
			this._login.hide ();
			this._login.unref ();
			this._login = null;
		}
	}
	
	,_freeGui: function ()
	{
		if (this._gui)
		{
			this._gui.disconnectByInstance (this);
			this._gui.hide ();
			this._gui.unref ();
			this._gui = null;
		}
	}
	
	,_destroy: function ()
	{
		this._freeLogin ();
		this._freeGui ();
		this._conn.unref ();
	}
});

