define([
	'js/system/client',
	'ui/factory',
	'js/rendering/renderer',
	'js/objects/objects',
	'js/rendering/effects',
	'js/rendering/numbers',
	'js/input',
	'js/system/events',
	'js/resources',
	'ui/templates/inventory/inventory',
	'ui/templates/equipment/equipment',
	'ui/templates/stash/stash',
	'ui/templates/hud/hud',
	'ui/templates/online/online',
	'ui/templates/quests/quests',
	'ui/templates/events/events',
	'ui/templates/dialogue/dialogue',
	'ui/templates/smithing/smithing',
	'ui/templates/overlay/overlay',
	'ui/templates/tooltips/tooltips',
	'ui/templates/reputation/reputation',
	'ui/templates/death/death',
	'ui/templates/passives/passives'
], function (
	client,
	uiFactory,
	renderer,
	objects,
	effects,
	numbers,
	input,
	events,
	resources
) {
	return {
		hasFocus: true,

		init: function () {
			client.init(this.onClientReady.bind(this));
		},

		onClientReady: function () {
			client.request({
				module: 'clientConfig',
				method: 'getResourcesList',
				callback: this.onGetResourceList.bind(this)
			});
		},

		onGetResourceList: function (list) {
			resources.init(list);

			events.on('onResourcesLoaded', this.start.bind(this));
		},

		start: function () {
			window.onfocus = this.onFocus.bind(this, true);
			window.onblur = this.onFocus.bind(this, false);
			$(window).on('contextmenu', function (e) {
				var allowedList = ['txtUsername', 'txtPassword'];

				var allowed = allowedList.some(function (item) {
					return $(e.target).hasClass(item);
				});

				if (!allowed) {
					e.preventDefault();
					return false;
				}
			});

			objects.init();
			renderer.init();
			input.init();

			numbers.init();

			uiFactory.init();
			uiFactory.build('login', 'body');

			this.update();
			this.render();
		},

		onFocus: function (hasFocus) {
			//Hack: Later we might want to make it not render when out of focus
			this.hasFocus = true;

			if (!hasFocus)
				input.resetKeys();
		},

		render: function () {
			numbers.render();

			renderer.render();

			requestAnimationFrame(this.render.bind(this));
		},
		update: function () {
			objects.update();
			renderer.update();
			uiFactory.update();

			setTimeout(this.update.bind(this), 16);
		}
	};
});
