// initialize popup position
function positionPopup() {
	var width = window.innerWidth;
	var height = window.innerHeight;
	// IE uses document.documentElement.client* instead of window.inner* so check to see if it was set properly
	if (typeof window.innerWidth == 'undefined') width = document.documentElement.clientWidth;
	if (typeof window.innerHeight == 'undefined') height = document.documentElement.clientHeight;
	// determine the scrollTop value, attempt to get from document.documentElement (IE/Firefox) else document.body.scrollTop (Chrome/Webkit)
	var scrollTop = document.documentElement.scrollTop >= document.body.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop;
	// if the height of the popup window (content + controls + margin) is greater than the height of the page move the window and shrink the content
	if (e('popupContent').scrollHeight + 24 > height) {
		e('popupWrapper').style.top = (2 + scrollTop) + 'px';
		e('popupContent').style.height = (height - 24) + 'px';
	}
	// otherwise set the content height to auto and move the window top properly to suit the scroll of the browser
	else {
		e('popupContent').style.height = '';
		e('popupWrapper').style.top = ((height - e('popupWrapper').scrollHeight) / 2 + scrollTop) + 'px';
	}
	// place the popup window on the screen
	e('popupWrapper').style.left = ((width - e('popupWrapper').scrollWidth) / 2) + 'px';
}

// display the popup
function showPopup() {
	d('popupMask', true);
	e('popupMask').onclick = cancelPopup;
	d('popupWrapper', true);
	// set the event handlers
	document.onkeyup = keyHandler;
	window.onscroll = positionPopup;
	window.onresize = positionPopup;

	positionPopup();
	updatePopup('');
}
// hide the popup
function hidePopup() {
	// unset the event handlers
	document.onkeyup = null;
	window.onscroll = null;
	window.onresize = null;

	d('popupMask', false);
	e('popupMask').onclick = null;
	d('popupWrapper', false);
}
// displays the popup with the content of the desired page
function getModule(url) {
	getModuleCalled = true;
	showPopup();
	document.location.hash = '#' + url.substring(1);
}

// opens a URL within popup.php
function openPopupURL(url) {
	client.open('GET', 'popup.php' + url, true);
	client.onreadystatechange = clientHandler;
	client.send(null);
}

// closes the popup and reloads the main page
function cancelPopup() {
	if (client.readyState != 0 && client.readyState != 4) client.abort();
	e('popupContent').innerHTML = '';
	hidePopup();

	// reload if the main window is a URL without an id
	if (module != 'view') {
		document.location.hash = '#none';
	}
}

// called every time the ready state of the popup changes
function clientHandler() {
	// NOTE: "readyState" is UNSENT = 0, OPENED = 1, HEADERS_RECEIVED = 2, LOADING = 3, DONE = 4
	if (this.readyState == 0) {
		return;
	}
	if (this.readyState == 1) {
		return;
	}

	// wrap this in a try...catch as implementations of the XMLHttpRequest in IE7/8 and Safari may not have the "status" property initiated at these states.
	try {
		if (this.readyState == 2) {
			return;
		}
		// this entire state is a hack for Safari, as it won't run the getResponseHeader function in state 2
		if (this.readyState == 3) {
			return;
		}
	}
	// consume the error, do nothing!
	catch (exp) {}

	if (this.readyState == 4) {
		// check if this is a redirection response, redirect the popup window
		if (this.status == 201 && this.getResponseHeader('Location')) {
			return;
		}
		if (this.status != 200 && this.status != 201 && this.status != 409 && this.status != 403) {
			return;
		}
		else if (this.status == 403) {
			return;
		}
		else if (this.responseText == '' && !this.getResponseHeader('Location')) {
			return;
		}
		else if (this.responseText == '') {
			return;
		}

		updatePopup(this.responseText);
	}
}

// updates the popup status, sets content and applies javascript to the popup window
function updatePopup(content) {
	e('popupContent').innerHTML = content;

	// run javascript
	var scripts = e('popupContent').getElementsByTagName('script');
	for (j = 0; j < scripts.length; j++) {
		// check if window.execScript (IE proprietary method for executing code in global scope)
		if (window.execScript) {
			window.execScript(scripts[j].innerHTML);
		}
		// force into global scope (TODO: test across browsers)
		else {
			window.eval(scripts[j].innerHTML);
		}
	}

	positionPopup();
	updateLinks(document.getElementById('popupContent'));
}

// obtains the name of the module, minus the entity name
function extractModule(url) {
	var module = url;
	// URL may be an object (such as that provided by document.location) so convert the object to a string, if it is not already
	if (typeof module != 'string') module = module.toString();

	// modify the module to remove everything before the first ? and after the first #
	if (module.indexOf('#') >= 0) module = module.substring(0, module.indexOf('#'));
	if (module.indexOf('?') > 0) module = module.substring(module.indexOf('?'));

	// if the first character of the modified module is not a '?', or if the module contains a '&' and doesn't start with '?m=' it's not a valid module
	if (module.substring(0, 1) != '?' || (module.indexOf('&') > -1 && module.substring(0, 3) != '?m=')) return '';

	// modify the module to remove the all additional data, the '?', '?m=' and any additional parameters ('&')
	var module = module.substring(1);
	if (module.substring(0, 2) == 'm=') module = module.substring(2);
	if (module.indexOf('&') > -1) module = module.substring(0, module.indexOf('&'));

	// if module contains any '/', then the value needed is everything from the last '/' onwards
	if (module.indexOf('/') > -1) module = module.substring(module.lastIndexOf('/') + 1).toLowerCase();
	return module;
}

// updates the links on a page to call 'getModule' when clicked
function updateLinks(element) {
	var links = element.getElementsByTagName('a');
	for (var i = 0; i < links.length; i++) {
		var m = links[i].getAttribute('href');
		m = extractModule(m);
		if (!m || m != 'view') continue;

		// IE7 gets the full path to do a link, shorten it to relative path
		var address = links[i].getAttribute('href');
		if (address.indexOf('?') > 0) address = address.substring(address.indexOf('?'));
		links[i].setAttribute('href', 'javascript:void(getModule(\'' + address + '\'));');
	}
}

function keyHandler(event) {
	if (!event) event = window.event;
	if (event.keyCode == 27) cancelPopup();
}

// determines what to do about a URL in response to a hash change
function changePopupOnHashChange() {
	// if there is no hash, return, the browser will request the page
	if (!document.location.hash) return;

	currentHash = document.location.hash.substring(1);
	// get the module name
	var m = extractModule('?' + currentHash);
	// if the module is not a view page close the popup
	if (!m || m != 'view') {
		cancelPopup();
	}
	// else reload the page with the new module
	else {
		if (!getModuleCalled) getModule('?' + currentHash);
		getModuleCalled = false;
		openPopupURL('?' + currentHash);
	}
}

// checks to see if the hash has changed based on a timer
function hashChangeTimerHandler() {
	var currentHash = document.location.hash.substring(1);
	if (currentHash == previousHash) return;
	previousHash = currentHash;
	changePopupOnHashChange();
}

// assign a function to the windows, if it is supported
var currentHash = previousHash = document.location.hash.substring(1);
if (window.onhashchange) window.onhashchange = changePopupOnHashChange;
else var hashChangeCheckInterval = setInterval(hashChangeTimerHandler, 200);

// generate a new XMLHttpRequest
var client = new XMLHttpRequest();
// track when getModule was called
var getModuleCalled = false;

// obtain the module to do some checks
var module = extractModule(document.location.search);

// If the document has a hash (and isn't '#' or '#none') then open that hash in a popup window
if (document.location.hash && document.location.hash != '#' && document.location.hash != '#none') {
	getModule('?' + document.location.hash.substring(1));
	openPopupURL('?' + document.location.hash.substring(1));
}

updateLinks(document.getElementById('content'));

