/*
 * previewer.js
 *
 *
 * Provides functionality for the Preview box.
 *
 *
 * Written by Arimah
 * http://arimah.beoch.net/
 *
 *
 * Do not use without permission.
 */

(function() {

function initPreviewer() {
	if ($A.getCurrentMedia() != "screen" ||
		$A.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);
			}, 1250);
		};
		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");
	var len = anchors.length;
	for (var i = 0; i < len; i++) {
		var anchor = anchors[i];
		if (!anchor.getAttribute("rel"))
			initAnchor(anchor);
	}
}


// Initializes the previewer box and its associated functionality.
function initPreviewBox() {
	var previewer = {};

	var div = previewer.div = $A.create("div", {id: "previewer"});
	var dstyle = div.style;

	div.appendChild($A.create("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++)
		div.appendChild($A.create("div", {className: decors[i]}));

	var scrollArea = $A.create("div", {id: "pbscrollarea"});
	div.appendChild(scrollArea);
	
	var content = $A.create("div", {id: "pbcontent"});
	scrollArea.appendChild(content);

	$A.body.appendChild(div);

	var reqPreview = null;
	function reqComplete(r) {
		if (r.status == 200) { // success!
			hideLoadingImage();
			content.innerHTML = r.responseText;
			startScrolling();
		} else { // oh shit
			if (!imgLoading) // this should never be the case
				showLoadingImage();
			imgLoading.src = "/img/loading_error.png"; // error icon
		}
	};

	var imgLoading = null;
	function showLoadingImage(oncomplete) {
		if (imgLoading) {
			oncomplete();
			return;
		}

		$A.preload("loading.gif", function(image) {
			if (imgLoading) return;

			imgLoading = $A.create("img", {id: "pbloading", src: "/img/loading.gif"});
			imgLoading.style.top  = ((div.offsetHeight - 5 - image.height) / 2)+"px";
			imgLoading.style.left = ((div.offsetWidth - 5 - image.width) / 2)+"px";

			div.appendChild(imgLoading);

			if (oncomplete)
				oncomplete();
		});
	}
	function hideLoadingImage() {
		if (imgLoading)
			div.removeChild(imgLoading);
		imgLoading = null;
	}

	previewer.show = function(anchor) {
		if (previewer.currentTarget == anchor)
			return;

		previewer.currentTarget = anchor;
		dstyle.visibility = "hidden";
		dstyle.display = "block";
		dstyle.top = dstyle.left = "0px";

		var anchorPos = $A.getElemPos(anchor);

		dstyle.left = Math.ensureInRange(0, $A.getWindowWidth() - div.offsetWidth,
			anchorPos[0] + (anchor.offsetWidth - div.offsetWidth + 5) / 2)+"px";

		var anchorY = anchorPos[1] + anchor.offsetHeight - 1;
		if (anchorY + div.offsetHeight > $A.getWindowHeight()+$A.getYScroll())
			anchorY = anchorPos[1] - div.offsetHeight;
		dstyle.top = anchorY + "px";

		content.innerHTML = ""; // make sure the content area is empty!
		dstyle.visibility = "visible";

		if (reqPreview)
			reqPreview.abort(); // abort previous

		showLoadingImage(function() {
			var url = anchor.getAttribute("href").match(/^([^\?#]*)\??([^#]*)/);
			reqPreview = $A.ajax({
				method: "get",
				url: url[1]+"?preview"+(url[2] && "&"+url[2]),
				oncomplete: reqComplete
			});
		});
	};
	previewer.hide = function() {
		if (reqPreview)
			reqPreview.abort(); // abort any pending request
		previewer.currentTarget = null;
		dstyle.display = "none";
		content.innerHTML = ""; // make sure content area is emptied!
		hideLoadingImage(); // make sure it's hidden
		stopScrolling();
		resetScroll();
	};
	var scrollIntervalId = null;
	var currentScroll = 0;
	var goingUp = 0;
	function startScrolling(nowait) {
		if (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 < 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;
				}

				content.style.marginTop = -currentScroll+"px";
			}, 50);
		}, nowait ? 0 : 2000); // wait before scrolling
	}
	function stopScrolling() {
		window.clearInterval(scrollIntervalId);
	}
	function resetScroll() {
		content.style.marginTop = (currentScroll = 0)+"px";
		goingUp = 0;
	}

	// mouse events
	div.onmouseover = function(e) {
		if (!e) e = window.event;
		var source = e.target || e.srcElement;
		
		while (source && source != content)
			source = source.parentNode;

		if (source == content)
			stopScrolling();
	};
	div.onmouseout = function(e) {
		if (!e) e = window.event;
		var source = e.target || e.srcElement;
		var target = e.relatedTarget || e.toElement;

		while (target && target != div)
			target = target.parentNode;
		
		while (source) {
			if (source == content) {
				startScrolling(true); // true = no delay
				return;
			} else if (source == div && target != div) {
				previewer.hide();
				return;
			}
			source = source.parentNode;
		}
	};

	return previewer;
}

$A.onload(initPreviewer);

})();