// Polyfill for .isArray().
if (!Array.isArray) {
	Array.isArray = function(arg) {
		return Object.prototype.toString.call(arg) === '[object Array]';
	};
}

// Takes a hook object and registers it to the global hooks list.
this.registerHook = function (oHook) {
	// Validate arguments
	if (typeof(oHook) !== 'object') {
		throw 'registerHook() - argument oHook is required and must be an object.';
	}

	if (typeof(oHook.name) !== 'string') {
		throw 'registerHook() - On argument oHook, the property \'name\' is required and must be a string.';
	}

	if (typeof(oHook.func) !== 'function') {
		throw 'registerHook() - On argument oHook, the property \'func\' is required and must be a function.';
	}

	if (oHook.pages !== undefined && typeof(oHook.pages) !== 'string' && !Array.isArray(oHook.pages)) {
		throw 'registerHook() - On argument oHook, the property \'pages\' must be a string or array of strings (if specified).';
	}

	// Create the global hooks list if it doesn't exist.
	if (typeof oHooks === 'undefined') {
		window.oHooks = {};
	}

	// Store the hook in the hooks list.
	window.oHooks[oHook.name] = oHook;
}

// Looks for and runs a hook in the global hooks list, optionally passing it an argument (an object)
// and a reference for "this".
this.runHook = function (sName, oArgs, oRetVals, _this) {
	function getPageName() {
		var pageName;

		// For backwards compatibility, this only uses the getOriginalPageName function when
		// defined. It is supposed to be defined in the template. It cannot be defined here since it depends on an ASP variable and this file is included as a script include.
		if (typeof getOriginalPageName === 'function') {
			pageName = getOriginalPageName();
		}

		if (!pageName) {
			var sUrl      = window.location.pathname;
			var iSlashIndex = sUrl.lastIndexOf("/");

			pageName = sUrl.substr(iSlashIndex + 1);
		}

		return pageName;
	}

	// Verifies that the current page is in the hook's list of allowed pages.
	function meetsPagesRequirement(oHook) {
		// Omitting the pages property ('undefined') indicates the hook is globally available.
		var pageName = getPageName();
		return (oHook.pages === undefined ||
		        oHook.pages === pageName ||
		        $.inArray(pageName, oHook.pages) !== -1);
	}

	// Validate arguments.
	if (typeof(sName) !== 'string') {
		throw 'runHook() - argument sName is required and must be a string.';
	}

	if (oArgs !== undefined && typeof(oArgs) !== 'object') {
		throw 'runHook() - argument oArgs must be an object (if specified).';
	}

	if (oRetVals !== undefined && typeof(oRetVals) !== 'object') {
		throw 'runHook() - argument oRetVals must be an object (if specified).';
	}

	if (_this !== undefined && typeof(_this) !== 'object') {
		throw 'runHook() - argument _this must be an object (if specified).';
	}

	// Check that the global hooks object exists.
	if (typeof(oHooks) !== 'undefined') {
		// Get the specific hook object that is being called.
		var oHook = oHooks[sName];

		// Make sure the hook object exists and that it's page requirements are met.
		if (oHook !== undefined && meetsPagesRequirement(oHook)) {
			// Call the hook function and return true to indicate a hook was run.
			oHook.func.call(_this, oArgs, oRetVals);
			return true;
		}
	}

	// Return false because a hook was not run.
	return false;
}