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();

		var conn = new Db.Connection();
		this.link({_conn: conn}, {'error': this._onConnError});

		this.initAutoLogin();
	}
	
	,run: function() {
		if (this.tryAutoLogin())
			return;
	
		var login = this._login = new Login({conn: this._conn});
		login.on('login', this._onLogin, this);
		login.show();
	}
	
	,_onLogin: function() {
		this._freeLogin();

		if (this._gui)
			return;
		
		var gui = this._gui = new Gui({conn: this._conn});
		gui.on('logout', this._onLogout, this);
		gui.show();
	}
	
	,_onLogout: function() {
		this.clearAutoLogin();
		this._freeGui();
		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)
		switch (error.exception) {
			case 'BadLogin':
				Htk.Toast.showError(_('Invalid login'));
				this._logout();
				break;
			case 'Forbidden':
				Htk.Toast.showError(_('You don\'t have enough privileges'));
				break;
			case 'UserDisabled':
				Htk.Toast.showError(_('User disabled'));
				this._logout();
				break;
			case 'SessionExpired':
				Htk.Toast.showError(_('Session expired'));
				this._logout();
				break;
			case 'OutdatedVersion':
				this._newVersion(error);
				break;
			default:
				Htk.Toast.showError(error.message);
		} else if (error.statusCode)
		switch (error.statusCode) {
			case 401:
				Htk.Toast.showError(_('Invalid login'));
				this._logout();
				break;
			default:
				Htk.Toast.showError(error.message);
		}
		else {
			console.error(error);
			this._notifyError(error);
		}
	}
	
	,_logout: function() {
		if (this._gui)
			this._gui.logout();
	}
	
	,_newVersion: function() {
		if (this.ignoreVersion)
			return;

		this.ignoreVersion = true;

		var dialog = new Htk.Dialog({
			 message: _('New version available')
			,buttons: Htk.Dialog.Button.ACCEPT
			,icon: 'warning'
		});
		dialog.on('response', this._onNewVersionResponse, this);
		dialog.open();
	}
	
	,_onNewVersionResponse: function() {
		location.reload();
	}
	
	,_notifyError: function(error) {
		Htk.Toast.showError(_('Something went wrong'));

		var params = {
			 file: error.fileName
			,line: error.lineNumber
			,message: error.message
			,stack: error.stack
			,agent: navigator.userAgent
			,location: location.href
		};
		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.deinitAutoLogin();
		this._conn.unref();
	}
	
	// Auto login functionality
	
	,_firstLogin: true

	,initAutoLogin: function() {
		var isGuest = new Vn.HashParam({
			type: Boolean,
			key: 'guest'
		});
		this.link({_isGuest: isGuest}, {'changed': this._onGuestChange});

		var token = new Vn.HashParam({
			type: String,
			key: 'token'
		});
		this.link({_token: token}, {'changed': this._onTokenChange});
	}
	
	,_onGuestChange: function() {
		if (this._isGuest.value)
			setTimeout(this.tryAutoLogin.bind(this));
	}
	
	,_onTokenChange: function() {
		if (this._token.value)
			setTimeout(this.tryAutoLogin.bind(this));
	}
	
	,deinitAutoLogin: function() {
		this._isGuest.unref();
		this._token.unref();
	}

	,autoLogin: function() {
		var guest = localStorage.getItem('hederaGuest');

		if (this._isGuest.value || guest) {
			localStorage.setItem('hederaGuest', true);
			return true;
		}

		if (this._token.value)
			this._conn.token = this._token.value;
		else
			this._conn.fetchToken();
		
		if (this._conn.token)
			return true;

		return false;
	}
	
	,tryAutoLogin: function() {
		var ok = this.autoLogin();

		this._firstLogin = false;
		this._isGuest.value = undefined;
		this._token.value = undefined;

		if (!ok)
			return false;

		this._onLogin();
		return true;
	}
	
	,clearAutoLogin: function() {
		localStorage.removeItem('hederaGuest');
	}
});