/*
**     JavaScript Source Code
**     Created by Kalin Ganev
**     <KalinGanev [AT] Gmail (DOT) com>
**     Date Created:  2008-07-08
**     Last Modified: 2011-12-29
**     Note: AlertManager class definition.
*/





// A global variable needed for preventing page scrolling during processing alert events:
var  gint_bodyScrollTop = 0;


function AlertManager () {

	// OBJECT MEMBERS:
	this.obj_functionOnScrollOld = null;
	// Alert item queue:
	this.arr_alertItems = new Array();
	// JavaScript source codes to execute array only for immediate visible alert items:
	this.strarr_jsCodesToExecuteImmediateVisible = new Array();
	this.bool_isProcessing = false;
	this.int_bodyScrollTop = 0;


	// OBJECT METHODS:
	this.getScreenWidth = function /*int*/ () {
		var  x = 0;

		if (self.innerHeight) {
			// All except Explorer.
			x = self.innerWidth;
		} else {
			if (document.documentElement && document.documentElement.clientHeight) {
				// Explorer 6 Strict Mode.
				x = document.documentElement.clientWidth;
			} else {
				if (document.body) {
					// Other Explorers.
					x = document.body.clientWidth;
				}
			}
		}
		return x;
	}


	this.getScreenHeight = function /*int*/ () {
		var  y = 0;

		if (self.innerHeight) {
			// All except Explorer.
			y = self.innerHeight;
		} else {
			if (document.documentElement && document.documentElement.clientHeight) {
				// Explorer 6 Strict Mode.
				y = document.documentElement.clientHeight;
			} else {
				if (document.body) {
					// Other Explorers.
					y = document.body.clientHeight;
				}
			}
		}
		return y;
	}


	this.getBodyScrollTop = function /*int*/ () {
		var  int_pos = 0;

		if (window.pageYOffset) {
			int_pos = window.pageYOffset;
		} else {
			if (document.documentElement && document.documentElement.scrollTop) {
				int_pos = document.documentElement.scrollTop;
			} else {
				if (document.body) {
					int_pos = document.body.scrollTop;
				}
			}
		}
		return int_pos;
	}


	this.darkenScreen = function /*void*/ () {
		if (document.getElementById('Overlay')) {
			document.getElementById('Overlay').style.top    = this.getBodyScrollTop() + 'px';
			document.getElementById('Overlay').style.height = this.getScreenHeight()  + 'px';
			document.getElementById('Overlay').style.visibility = 'visible';
		} else {
			// Error.
			window.alert('AlertManager::darkenScreen():void method: "Overlay" HTML layer could not be found!');
		}

		// Hiding select-boxes as they cannot be covered with a layer in IE:
		var  objarr_selectBoxes = document.getElementsByTagName('select');
		for (var i=0; i<objarr_selectBoxes.length; i++) {
			objarr_selectBoxes[i].style.visibility = 'hidden';
		}

		// Hiding objects (Flash elements) as they cannot be covered with a layer:
		var  objarr_objectElements = document.getElementsByTagName('object');
		for (var i=0; i<objarr_objectElements.length; i++) {
			objarr_objectElements[i].style.visibility = 'hidden';
		}

		// Hiding embeds (Flash elements):
		var  objarr_embedElements = document.getElementsByTagName('embed');
		for (var i=0; i<objarr_embedElements.length; i++) {
			objarr_embedElements[i].style.visibility = 'hidden';
		}
	}


	this.clearUpScreen = function /*void*/ () {
		if (document.getElementById('Overlay')) {
			document.getElementById('Overlay').style.visibility = 'hidden';
		} else {
			// Error.
			window.alert('AlertManager::clearUpScreen():void method: "Overlay" HTML layer could not be found!');
		}

		// Unhiding select-boxes:
		var  objarr_selectBoxes = document.getElementsByTagName('select');
		for (var i=0; i<objarr_selectBoxes.length; i++) {
			objarr_selectBoxes[i].style.visibility = 'visible';
		}

		// Unhiding objects (Flash elements):
		var  objarr_objectElements = document.getElementsByTagName('object');
		for (var i=0; i<objarr_objectElements.length; i++) {
			objarr_objectElements[i].style.visibility = 'visible';
		}

		// Unhiding embeds (Flash elements):
		var  objarr_embedElements = document.getElementsByTagName('embed');
		for (var i=0; i<objarr_embedElements.length; i++) {
			objarr_embedElements[i].style.visibility = 'visible';
		}
	}


	this.showMsgBox = function /*void*/ (str_htmlMsg) {
		if (document.getElementById('MsgBox')) {
			this.darkenScreen();
			document.getElementById('MsgBox-Content-Html').innerHTML = str_htmlMsg;
			document.getElementById('MsgBox').style.left = parseInt((this.getScreenWidth()
					- document.getElementById('MsgBox').clientWidth) / 2) + 'px';
			document.getElementById('MsgBox').style.top  = parseInt((this.getScreenHeight()
					- document.getElementById('MsgBox').clientHeight) / 2 + this.getBodyScrollTop()) + 'px';
			document.getElementById('MsgBox').style.visibility = 'visible';
			document.getElementById('MsgBox-Btn-Ok').focus();

			// Preventing page scrolling:
			gint_bodyScrollTop = this.getBodyScrollTop();
			this.obj_functionOnScrollOld = window.onscroll;
			window.onscroll = function (event) {
				window.scrollTo(0, gint_bodyScrollTop);
			}
		} else {
			// Error.
			window.alert('AlertManager::showMsgBox(String):void method: "MsgBox" HTML layer could not be found!'
					+ '\nThe default window.alert() method will be used instead for displaying current alert message.');
			// Displaying alert message anyway:
			window.alert(str_htmlMsg);
		}
	}


	this.executeJavaScriptCode = function /*boolean*/ (str_jsCodeToExecute) {
		try {
			window.eval(str_jsCodeToExecute);
			return true;
		} catch (e) {
			$.msgbox('AlertManager::executeJavaScriptCode():boolean method: An error arose while executing current JavaScript source code!<br/>'
					+ e.message, {type: 'error'});
			return false;
		}
	}


	this.triggerAlertItem = function /*void*/ (str_htmlMsg, str_nameSound, bool_isVisible, str_jsCodeToExecute) {
		if (str_nameSound.length > 0) {
			// Current alert item has a sound to play.
			try {
				soundManager.play(str_nameSound);
			} catch (e) {
				window.alert('AlertManager::triggerAlertItem():void method: SoundManager is not configured properly!');
			}
		}
		if (bool_isVisible) {
			this.showMsgBox(str_htmlMsg);
		} else {
			// Current alert item is invisible.
			// Executing its JavaScript source code immediately:
			this.executeJavaScriptCode(str_jsCodeToExecute);
		}
	}


	this.processQueue = function /*void*/ () {
		for (var i=0; i<this.arr_alertItems.length; i++) {
			var  arr_alertItemCurr = this.arr_alertItems[i];
			if (!arr_alertItemCurr[4]) {
				// OK: Found an alert item that has never been displayed before (not completed).
				if (arr_alertItemCurr[2]) {
					// OK: Current alert item is visible.
					this.bool_isProcessing = true;
				}
				this.triggerAlertItem(arr_alertItemCurr[0], arr_alertItemCurr[1], arr_alertItemCurr[2], arr_alertItemCurr[3]);
				// Raising "is completed" flag of current alert item:
				arr_alertItemCurr[4] = true;
				if (arr_alertItemCurr[2]) {
					// Current alert item is visible.
					// Stopping processing the queue:
					break;
				} else {
					// Current alert item is invisible.
					// JavaScript source code of current alert item has been already executed
					// by AlertManager::triggerAlertItem():void method so it has to be cleared here:
					arr_alertItemCurr[3] = '';
				}
			}
		} // for
	}


	this.hideMsgBox = function /*void*/ () {
		if (document.getElementById('MsgBox')) {
			this.clearUpScreen();
			document.getElementById('MsgBox').style.visibility = 'hidden';
		} else {
			// Error.
			window.alert('AlertManager::hideMsgBox():void method: "MsgBox" HTML layer could not be found!');
		}
		// Restoring page scrolling:
		window.onscroll = this.obj_functionOnScrollOld;

		this.bool_isProcessing = false;
		this.processQueue();
		// Executing some JavaScript source codes:
		// For completed, not immediate, visible alert items:
		for (i=0; i<this.arr_alertItems.length && this.arr_alertItems[i][4]; i++) {
			this.executeJavaScriptCode(this.arr_alertItems[i][3]);
			// Clearing JavaScript source code of current alert item:
			this.arr_alertItems[i][3] = '';
		}
		// For immediate visible alert items:
		for (i=0; i<this.strarr_jsCodesToExecuteImmediateVisible.length; i++) {
			this.executeJavaScriptCode(this.strarr_jsCodesToExecuteImmediateVisible[i]);
			// Clearing JavaScript source code of current alert item:
			this.strarr_jsCodesToExecuteImmediateVisible[i] = '';
		}
	}


	/** This is the only one class public method (a method that should be called outside the class definition). */
	this.addAlertItem = function /*void*/ (str_htmlMsg, str_nameSound, bool_isVisible, bool_isImmediate, str_jsCodeToExecute) {
		// DEBUG:
		/*
		window.alert('AlertManager::addAlertItem(...):void debug message:\n\nstr_htmlMsg = ' + str_htmlMsg
				+ '\nstr_nameSound = ' + str_nameSound
				+ '\nbool_isVisible = ' + bool_isVisible
				+ '\nbool_isImmediate = ' + bool_isImmediate
				+ '\nstr_jsCodeToExecute = ' + str_jsCodeToExecute);
		*/
		// Focusing browser window:
		if (window.focus) {
			// Works in IE, not in Firefox.
			window.focus();
		}
		if (bool_isImmediate) {
			this.triggerAlertItem(str_htmlMsg, str_nameSound, bool_isVisible, str_jsCodeToExecute);
			if (bool_isVisible) {
				// Current immediate alert item is visible.
				// Adding its JavaScript source code to "JavaScript source codes to execute" member array:
				this.strarr_jsCodesToExecuteImmediateVisible.push(str_jsCodeToExecute);
			}
		} else {
			// Alert item is NOT immediate.  Adding it to alert item queue:
			var  bool_isCompleted = false;
			this.arr_alertItems.push(new Array(str_htmlMsg, str_nameSound, bool_isVisible, str_jsCodeToExecute, bool_isCompleted));
			if (!this.bool_isProcessing) {
				this.processQueue();
			}
		}
	} // addAlertItem() method

} // AlertManager class




// Creating a new global instance of AlertManager class:
var  gobj_manAlerts = new AlertManager();


