var Interface = {
	minWindowZIndex: 900,
	initialize: function () {
		this.background = $('dim_background');
		this.loadingElement = $('app_loading_panel');
		this.loadingDetails = $('app_loading_panel_details');

		this.dropMenus = new Array ();
		this.windows = new Array ();
		this.activeWindows = new Array ();
		this.registeredOnResize = new Array ();
		this.onBrowserResize();

		Event.observe(Prototype.Browser.IE?document:window, "click", this.onWindowClick.bindAsEventListener(this));
		Event.observe(window, "resize", this.onBrowserResize.bindAsEventListener(this));

		this.windowsContainer = $('windows_container');
	},
	registerOnResize: function (method) {
		this.registeredOnResize.push(method);
	},
	unregisterOnResize: function (method) {
		this.registeredOnResize = this.registeredOnResize.without(method);
	},
	onBrowserResize: function () {
		this.windowWidth = (window.innerWidth || document.body.offsetWidth || document.documentElement.offsetWidth);
		this.windowHeight = (window.innerHeight || document.body.offsetHeight || document.documentElement.offsetHeight);
		for (var i = 0, n = this.registeredOnResize.length; i < n; i ++)
			this.registeredOnResize[i](this.windowWidth, this.windowHeight);
	},
	showLoading: function (text) {
		document.body.style.cursor = 'wait';
		this.dimBackground();
		this.loadingElement.style.display = 'block';
		this.loadingDetails.innerHTML = text;
	},
	hideLoading: function () {
		document.body.style.cursor = '';
		this.undimBackground();
		this.loadingElement.style.display = 'none';
		this.loadingDetails.innerHTML = '';
	},
	appendLoadingText: function (text) {
		this.loadingDetails.innerHTML += text;
	},
	appendLoadingErrorText: function () {
		this.loadingDetails.innerHTML += "ERROR!<br /><span class=\"error\">Loading cannot continue. Sorry</span>";
	},
	dimBackground: function () {
		this.background.style.display = 'block';
	},
	undimBackground: function () {
		this.background.style.display = 'none';
	},
/* drop menus  */
	registerDropMenu: function (object) {
		this.dropMenus.push(object);
		object._onMenuDropped = this.onMenuDropped.bind(this);
	},
	unregisterDropMenu: function (object) {
		this.dropMenus = this.dropMenus.without(object);
	},
	onMenuDropped: function (event, menu) {
		this.hideAllMenus(menu); // hide all menus except this one!
		this.lastOpenedMenu = menu;
	},
	hideAllMenus: function (without) {
		if (arguments.length == 0)
			var m = this.dropMenus;
		else if (typeof(without) == "array")
			var m = this.dropMenus.without.apply(this.dropMenus, without);
		else
			var m = this.dropMenus.without(without);
		for (var i = 0, n = m.length; i < n; i ++)
			m[i].hide();
	},
	onWindowClick: function (event) {
		// check if the opened menu needs to close
		try {
			if (this.lastOpenedMenu && this.lastOpenedMenu.isMenuVisible()) {
				if (!Event.element(event).descendantOf(this.lastOpenedMenu.element)) {
					this.lastOpenedMenu.hide();
					this.lastOpenedMenu = null;
				}
			}
		} catch (e) {}
	},
/* floating windows  */
	registerWindow: function (object) {
		this.windows.push(object);
		this.windowsContainer.appendChild(object.element);
	},
	unregisterWindow: function (object) {
		this.activeWindows = this.activeWindows.without(window);
		this.windows = this.windows.without(object);
		this.resetWindowsZIndexes();
		this.windowsContainer.removeChild(object.element);
	},
	/**
	* @todo: Fix focus & blur events firing - they are toio often this way!
	**/
	resetWindowsZIndexes: function () {
		// so, this.activeWindows is kept in order from lowest z index to highest
		for (var i = 0, n = this.activeWindows.length; i < n; i ++) {
			this.activeWindows[i]._setZIndex(this.minWindowZIndex + i);
			if (i < n - 1) this.activeWindows[i].onBlur();
		}
		if (this.activeWindows.length > 0)
			this.activeWindows.last().onFocus();
	},
	bringToFront: function (window) {
		// move the window on top of the array
		this.activeWindows = this.activeWindows.without(window);
		this.activeWindows.push(window);
		this.resetWindowsZIndexes();
	},
	onWindowOpened: function (window) {
		this.activeWindows.push(window);
		this.resetWindowsZIndexes();
		if (window.dimBGonOpen) this.dimBackground();
	},
	onWindowClosed: function (window) {
		this.activeWindows = this.activeWindows.without(window);
		this.resetWindowsZIndexes();
		if (window.dimBGonOpen) this.undimBackground();
	},
/* Javascript runtime loader */
	loadJS: function (URL, async) {
		if (arguments.length == 1)
			var async = false;
		new Ajax.Request (URL, {method:'post', asynchronous: async, onSuccess: function (ar){
				var t = ar.responseText;
//				t = t.replace(/\/\/.*\n/g, '');
//				t = t.replace(/\n/g, ' ');
//				t = t.replace(/\/\*.+?\*\//g, '');
				try { eval(t); } catch (e) {if (console) console.error(e); $throw (e)};
			}
		});
	},
/* images preloading */
	cacheImage: function (URL) {
		var ni = new Image();
		ni.src = URL;
	}
};