/*
 * previewer.js
 *
 *
 * Provides functionality for the Preview box.
 *
 *
 * Written by Arimah
 * http://arimah.beoch.net/
 *
 *
 * Do not use without permission.
 */


function initPreviewer() {
	if (initPreviewer.hasRun) return;

	if (getCurrentMedia() != "screen") return;
	if (readCookie("preview") == "disabled")
		return;
	var previewer = initPreviewBox();

	var timeoutId = null;
	var initAnchor = function(anchor) {
			anchor.onmouseover = function() {
					if (previewer.currentTarget != anchor)
						previewer.hide();
					else
						return;

					window.clearTimeout(timeoutId);

					timeoutId = window.setTimeout(function() {
							previewer.show(anchor);
						}, 1500);
				};
			anchor.onmouseout = function(e) {
					if (!e) e = window.event;

					var target = e.relatedTarget || e.toElement;
					while (target && target != anchor &&
						target != previewer.div)
						target = target.parentNode;

					// don't hide previewer if we're mousing onto it
					if (target != previewer.div && target != anchor) {
						window.clearTimeout(timeoutId);
						previewer.hide();
					}
				};
		};

	var anchors = document.getElementsByTagName("a");
	for (var i = 0; i < anchors.length; i++) {
		var anchor = anchors[i];
		if (!anchor.getAttribute("rel"))
			initAnchor(anchors[i]);
	}

	initPreviewer.hasRun = true;
}


// Initializes the previewer box and its associated functionality.
function initPreviewBox() {
	var body = document.body || document.getElementsByTagName("body")[0];

	var previewer = {};

	previewer.div = document.createElement("div");
	previewer.div.setAttribute("id", "previewer");

	previewer.div.appendChild(document.createElement("hr"));

	var decors = [ "n w", "n middle", "n e", "w middle", "e middle", "s w", "s middle", "s e" ];
	for (var i = 0; i < decors.length; i++) {
		var decor = document.createElement("div");
		decor.className = decors[i];
		previewer.div.appendChild(decor);
	}

	var scrollArea = document.createElement("div");
	scrollArea.setAttribute("id", "pbscrollarea");
	previewer.div.appendChild(scrollArea);
	
	previewer.content = document.createElement("div");
	previewer.content.setAttribute("id", "pbcontent");
	scrollArea.appendChild(previewer.content);

	body.appendChild(previewer.div);

	var reqPreview = new XMLHttpRequest();

	var imgLoading = null;
	var showLoadingImage = function(oncomplete) {
			if (imgLoading) {
				oncomplete();
				return;
			}

			preloadImage("loading.gif",
				function(image) {
					if (imgLoading) return;

					imgLoading = document.createElement("img");
					imgLoading.setAttribute("id", "pbloading");
					imgLoading.src = "img/loading.gif";
					imgLoading.style.top  = ((previewer.div.offsetHeight - 5 - image.height) / 2)+"px";
					imgLoading.style.left = ((previewer.div.offsetWidth - 5 - image.width) / 2)+"px";

					previewer.div.appendChild(imgLoading);

					if (typeof oncomplete == "function")
						oncomplete();
				});
		};
	var hideLoadingImage = function() {
			if (imgLoading) {
				previewer.div.removeChild(imgLoading);
			}
			imgLoading = null;
		};

	previewer.show = function(anchor) {
			if (previewer.currentTarget == anchor)
				return;

			previewer.currentTarget = anchor;
			previewer.div.style.visibility = "hidden";
			previewer.div.style.display = "block";
			previewer.div.style.top = previewer.div.style.left = "0px";

			var anchorPos = getElemPos(anchor); // getElemPos defined in common.js

			previewer.div.style.left = Math.ensureInRange(0, getWindowWidth() - previewer.div.offsetWidth,
				anchorPos[0] + (anchor.offsetWidth - previewer.div.offsetWidth + 5) / 2)+"px";

			var anchorY = anchorPos[1] + anchor.offsetHeight;
			if (anchorY + previewer.div.offsetHeight > getWindowHeight()+getYScroll())
				anchorY = anchorPos[1] - previewer.div.offsetHeight;
			previewer.div.style.top = anchorY + "px";

			previewer.content.innerHTML = ""; // make sure the content area is empty!
			previewer.div.style.visibility = "visible";

			reqPreview.abort(); // abort previous

			showLoadingImage(function() {
					var url = anchor.getAttribute("href").split("#");
					reqPreview.open("get", url[0]+"&preview"+(url[1] ? "#"+url[1] : ""));
					reqPreview.send(null);
				});
		};
	previewer.hide = function() {
			reqPreview.abort(); // abort any pending request
			previewer.currentTarget = null;
			previewer.div.style.display = "none";
			previewer.content.innerHTML = ""; // make sure content area is emptied!
			hideLoadingImage(); // make sure it's hidden
			previewer.stopScrolling();
			previewer.resetScroll();
		};
	reqPreview.onreadystatechange = function() {
			if (reqPreview.readyState == 4) { // request completed
				if (reqPreview.status == 200) { // success!
					hideLoadingImage();
					previewer.content.innerHTML = reqPreview.responseText;
					previewer.startScrolling();

				} else { // oh shit
					if (!imgLoading) // this should never be the case
						showLoadingImage();
					imgLoading.src = "img/loading_error.png"; // error icon
				}
			}
		};
	var scrollIntervalId = null;
	var currentScroll = 0;
	var goingUp = 0;
	previewer.startScrolling = function(nowait) {
			if (previewer.content.offsetHeight < scrollArea.offsetHeight)
				return; // nothing to scroll; this will probably never happen

			scrollIntervalId = window.setInterval(function() {
					window.clearInterval(scrollIntervalId);
					scrollIntervalId = window.setInterval(function() {
						if (currentScroll < previewer.content.offsetHeight-scrollArea.offsetHeight+10 &&
							!goingUp)
							currentScroll++;
						else {
							// if goingUp is between 0 and 20, we're waiting to go back up;
							// if goingUp is less than 0, we're waiting to start scrolling again
							if (goingUp >= 0 && goingUp < 20) {
								goingUp++;
								return;
							} else if (goingUp < 0) {
								goingUp--;
								if (goingUp == -20)
									goingUp = 0; // start scrolling
								return;
							}

							if (currentScroll <= 20)
								currentScroll -= Math.max(Math.floor(currentScroll / 2), 1);
							else
								currentScroll = Math.max(currentScroll - 80, 20);
							
							if (currentScroll == 0)
								goingUp = -1;
						}

						previewer.content.style.marginTop = -currentScroll+"px";
					}, 50);
				}, nowait ? 0 : 2000); // wait before scrolling
		};
	previewer.stopScrolling = function() {
			window.clearInterval(scrollIntervalId);
		};
	previewer.resetScroll = function() {
			previewer.content.style.marginTop = (currentScroll = 0)+"px";
			goingUp = 0;
		};

	// mouse events
	previewer.div.onmouseover = function(e) {
			if (!e) e = window.event;
			var source = e.target || e.srcElement;
			
			while (source && source != previewer.content)
				source = source.parentNode;

			if (source == previewer.content)
				previewer.stopScrolling();
		};
	previewer.div.onmouseout = function(e) {
			if (!e) e = window.event;
			var source = e.target || e.srcElement;
			var target = e.relatedTarget || e.toElement;

			while (target && target != previewer.div)
				target = target.parentNode;
			
			while (source) {
				if (source == previewer.content) {
					previewer.startScrolling(true); // true = no delay
					return;
				} else if (source == previewer.div &&
					target != previewer.div) {
					previewer.hide();
					return;
				}
				source = source.parentNode;
			}
		};

	return previewer;
}


addLoadEvent(initPreviewer); // addLoadEvent defined in common.js
preloadImage("loading.gif", null); // preloadImage defined in common.js

// IE compatibility crap
if (typeof XMLHttpRequest == "undefined")
	XMLHttpRequest = function() {
			try { return new ActiveXObject("Msxml2.XMLHTTP.6.0") } catch(e) {}
			try { return new ActiveXObject("Msxml2.XMLHTTP.3.0") } catch(e) {}
			try { return new ActiveXObject("Msxml2.XMLHTTP") } catch(e) {}
			try { return new ActiveXObject("Microsoft.XMLHTTP") } catch(e) {}
		};