/*
 * Wiki Summary Box 0.1.2
 * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com, http://blog.nihilogic.dk/
 * MIT License [http://www.opensource.org/licenses/mit-license.php]
 */


var __WikiCallbacks = {};

(function(){

	var showDelay = 200;
	var hideDelay = 300;

	var footerGFDLText = "(available under the <a href=\"http://en.wikipedia.org/wiki/Wikipedia:Text_of_the_GNU_Free_Documentation_License\" target=\"_blank\">GNU Free Documentation License</a>)."

	// List of wiki sites below, properties are:
	// basehost : base host of the wiki (ie. 
	// lang : if true, the "http://[langcode].[basehost]/" format is used, if false we simply use basehost
	// apipath : the relative path of api.php on the wiki host
	// name : The name that will be displayed in the footer
	// GFDL : if true, a GNU Free Documentation License notice will be shown in the footer
	// fullarticle : use full article, ie. don't just pick out the first paragraphs

	var wikiSites = [
		{basehost : "wikipedia.org", lang : true, apipath : "/w/api.php", articlepath : "/wiki/", name : "Wikipedia", licensetext : footerGFDLText},
		{basehost : "wikiquote.org", lang : true, apipath : "/w/api.php", articlepath : "/wiki/", name : "Wikiquote", licensetext : footerGFDLText, fullarticle : false},
		{basehost : "species.wikimedia.org", lang : false, apipath : "/w/api.php", articlepath : "/wiki/", name : "Wikispecies", licensetext : footerGFDLText, fullarticle : true, css : "wikispecies"},
		{basehost : "wikinews.org", lang : true, apipath : "/w/api.php", articlepath : "/wiki/", name : "Wikinews", licensetext : footerGFDLText, fullarticle : false},
		{basehost : "wikisource.org", lang : true, apipath : "/w/api.php", articlepath : "/wiki/", name : "Wikisource", licensetext : footerGFDLText, fullarticle : false},
		{basehost : "wikibooks.org", lang : true, apipath : "/w/api.php", articlepath : "/wiki/", name : "Wikibooks", licensetext : footerGFDLText, fullarticle : false},
		{basehost : "wiktionary.org", lang : true, apipath : "/w/api.php", articlepath : "/wiki/", name : "Wiktionary", licensetext : footerGFDLText, fullarticle : true, css : "wiktionary"},
		{basehost : "wikiversity.org", lang : true, apipath : "/w/api.php", articlepath : "/wiki/", name : "Wikiversity", licensetext : footerGFDLText, fullarticle : false}
	]

	var loaderText = "Loading...";

	var footerText = "Summary via <a href=\"[wiki_url]\" target=\"_blank\">[wiki_name]</a> "
	var footerArticleLink = "Read full article <a href=\"[article_url]\" target=\"_blank\">here</a>";

	var callCount = 0;

	var wikiResults = [];

	var visiWiki = null;

	var bodyHeight = 0;
	var bodyWidth = 0;

	var showTimer = 0;
	var hideTimer = 0;

	var dc = function(tag, className) {
		var el = document.createElement(tag);
		if (className)
			el.className = className;
		return el;
	};

	function sendRequest(site, keyword, lang, callback) {
		if (wikiResults[site.basehost+"_"+lang+"_"+keyword]) {
			if (callback)
				callback(wikiResults[site.basehost+"_"+lang+"_"+keyword]);
			return;
		}

		callCount++;

		lang = lang || "en";

		var url = "http://" + (site.lang ? (lang+"."+site.basehost) : site.basehost) + site.apipath + "?action=parse&prop=text&format=json&callback=__WikiCallbacks.fn_" + callCount + "&page=" + keyword;

		var script = document.createElement("script");

		__WikiCallbacks["fn_" + callCount] = function(res) {
			document.body.removeChild(script);

			if (!res.failed) {
				wikiResults[site.basehost+"_"+lang+"_"+keyword] = res;
			}
			if (callback)
				callback(res);
		};

		script.setAttribute("type", "text/javascript");
		document.body.appendChild(script);

		script.src = url
	}

	function addEvent(el, event, handler) {
		if (el.addEventListener)
			el.addEventListener(event, handler, false); 
		else if (el.attachEvent)
			el.attachEvent("on" + event, handler); 
	}

	function makeWikiLink(marker, site, keyword, lang) {
		if (site && keyword) {
			addEvent(marker, "mouseover", 
				function(e) {
					e = e || window.event;
					if (!marker.wiki || marker.wiki != visiWiki) {
						if (visiWiki) {
							hideWiki(visiWiki);
						}

						if (showTimer) {
							clearTimeout(showTimer);
						}
						showTimer = setTimeout(
							function() {
								marker.wiki = showWiki(marker, site, keyword, lang, e||window.event);
							},showDelay
						);
					}
				}
			);
			addEvent(marker, "mouseout",
				function() {
					if (showTimer) {
						clearTimeout(showTimer);
						showTimer = 0;
					}
				}
			);
		}
	}

	function getElementPos(el) {
		var x = 0;
		var y = 0;

		while (el && el.nodeName != "BODY") {
			x += el.offsetLeft;
			y += el.offsetTop;
			el = el.offsetParent;
		}

		return {
			x : x,
			y : y
		}
	}

	function cleanLinks(node, baseurl) {
		if (!node.hasChildNodes) return;
		for (var i=0;i<node.childNodes.length;i++) {
			var child = node.childNodes[i];
			if (child.tagName == "A") {
				if (child.getAttribute("tmphref") && child.getAttribute("tmphref").substring(0,1) == "/") {
					child.setAttribute("href", baseurl + child.getAttribute("tmphref"));
					child.setAttribute("target", "_blank");
				}
			} else {
				if (child.hasChildNodes) {
					cleanLinks(child, baseurl);
				}
			}
		}
		return node;
	}

	function showWiki(marker, site, keyword, lang, event) {
		if (visiWiki) {
			hideWiki(visiWiki);
		}

		if (showTimer) {
			clearTimeout(showTimer);
			showTimer = 0;
		}
		bodyHeight = document.body.clientHeight;
		if(bodyHeight==0){
		bodyHeight = document.documentElement.clientHeight;
		}
		bodyWidth = document.body.scrollWidth;

		var ctr = dc("div", "wiki-summary-container");
		if (site.css)
			ctr.className += " wiki-summary-" + site.css;
		var header = dc("div", "wiki-summary-header");
		var content = dc("div", "wiki-summary-content");
		var footer = dc("div", "wiki-summary-footer");

		ctr.appendChild(header);
		ctr.appendChild(content);
		ctr.appendChild(footer);

		var pos = getElementPos(marker);

		ctr.style.position = "absolute";
		ctr.style.left = pos.x+"px";
		ctr.style.top = pos.y+"px";

		ctr.style.display = "none";

		document.body.appendChild(ctr);
		ctr.marker = marker;

		var loader = dc("div", "wiki-summary-loader");
		loader.innerHTML = loaderText;
		content.appendChild(loader);

		sendRequest(site, keyword, lang,
			function(res) {
				var baseurl = "http://"+ (site.lang ? (lang+"."+site.basehost) : site.basehost);

				header.innerHTML = decodeURIComponent(keyword).replace(/_/g, " ");

				var rawContent = document.createElement("div");

				var rawHTML = res.parse.text["*"];

				// remove images, we don't want to leech off of the Wiki servers
				rawHTML = rawHTML.replace(/\<img\ .*?\>/g, "");


				// Argh, this is no fun. IE won't let us get the relative paths to other Wiki pages so we can't distinguish them from other links.
				// This is all I could think of so far: replace the href attribute with another temporary attribute and then switch it back later when 
				// we're walking the DOM tree of the Wiki content.
				rawContent.innerHTML = rawHTML.replace(/<a\ href\=\"/g, "<a tmphref=\"");

				var sumFragment = document.createDocumentFragment();

				if (site.fullarticle) {
					sumFragment.appendChild(cleanLinks(rawContent, baseurl));
				} else {
					var parNodes = [];
					for (var i=0;i<rawContent.childNodes.length;i++) {
						var node = rawContent.childNodes[i];
						if (node.tagName == "P") {
							var text = node.textContent || node.innerHTML || "";
							if (text.replace(/^\s*([\S\s]*?)\s*$/, '$1') == "") {
	                        				continue;
	                    				}
							parNodes.push([node, rawContent]);
						}
						if (node.tagName == "UL" || node.tagName == "OL") {
							for (var j=0;j<node.childNodes.length;j++) {
								if (node.childNodes[j].tagName == "LI")
									cleanLinks(node.childNodes[j], baseurl)
							}
							parNodes.push([node, rawContent]);
						}
						if (node.tagName == "H1" || node.tagName == "H2") {
							break;
						}
					}
					for (var i=0;i<parNodes.length;i++) {
						if (parNodes[i][0] && parNodes[i][1]) {
							parNodes[i][1].removeChild(parNodes[i][0]);
							sumFragment.appendChild(cleanLinks(parNodes[i][0], baseurl));
						}
					}
				}

				content.innerHTML = "";
				content.appendChild(sumFragment);

				var fullFooterText = footerText + site.licensetext + "<br>" + footerArticleLink;

				footer.innerHTML = 
					fullFooterText.replace(
						/\[article_url\]/g, 
						"http://" + (site.lang ? (lang+"."+site.basehost) : site.basehost) + site.articlepath + keyword
					).replace(
						/\[wiki_name\]/g, site.name
					).replace(
						/\[wiki_url\]/g, 
						"http://" + (site.lang ? (lang+"."+site.basehost) : site.basehost) + "/"
					);
			}
		);

		addEvent(ctr, "mouseout", 
			function(e) {
				var relTarget = (e.relatedTarget) ? e.relatedTarget : e.toElement;
				while (relTarget && relTarget != ctr && relTarget.nodeName != "BODY")
					relTarget = relTarget.parentNode
				if (relTarget == ctr) return;

				if (marker.wiki) {
					if (hideTimer) {
						clearTimeout(hideTimer);
					}
					hideTimer = setTimeout(
						function() {
							hideWiki(marker.wiki);
						}, hideDelay
					);
				}
			}
		);
		addEvent(ctr, "mouseover",
			function() {
				if (hideTimer) {
					clearTimeout(hideTimer);
					hideTimer = 0;
				}
			}
		);

		visiWiki = ctr;

		setTimeout(function() {
			ctr.style.display = "block";

			var x = Math.max(0, Math.min(bodyWidth - ctr.offsetWidth, pos.x));
			ctr.style.left = x+"px";

			var y = Math.max(0, Math.min(bodyHeight - ctr.offsetHeight, pos.y));
			ctr.style.top = y+"px";


		},1);

		return ctr;
	}

	function hideWiki(ctr) {
		try {
			document.body.removeChild(ctr);
			ctr.marker.wiki = null;
		} catch(e) {}
		visiWiki = null;
	}

	var initDone = false;

	function init() {
		if (initDone) return;

		initDone = true;
		var as = document.getElementsByTagName("a");
		var patterns = [];
		for (var j=0;j<wikiSites.length;j++) {
			patterns[j] = new RegExp("http:\\/\\/" + (wikiSites[j].lang ? "([^/]+)?\\." : "") + wikiSites[j].basehost.replace(/\./g, "\\.") + "\\" + wikiSites[j].articlepath + "([^/]+)");
		}
		for (var i=0;i<as.length;i++) {
			if (as[i].getAttribute("href")) {
				for (var j=0;j<wikiSites.length;j++) {
					var pattern = patterns[j];
					var href = as[i].getAttribute("href").match(pattern);

					if (wikiSites[j].lang) {
						if (href && href.length == 3) {
							makeWikiLink(as[i], wikiSites[j], href[2], href[1]);
							break;
						}
					} else {
						if (href && href.length == 2) {
							makeWikiLink(as[i], wikiSites[j], href[1], href[0]);
							break;
						}
					}
				}
			}
		}
	}


	function onready(handler) {
		var handlerDone = false;
		var execHandler = function() {
			if (!handlerDone) {
				handlerDone = true;
				handler();
			}
		}
		document.write("<"+"script defer src=\"//:\" id=\"__onload_ie_sumbox__\"></"+"script>");
		var script = document.getElementById("__onload_ie_sumbox__");
		script.onreadystatechange = function() {
			if (script.readyState == "complete") {
				script.parentNode.removeChild(script);
				execHandler();
			}
		}
		if (document.addEventListener)
			document.addEventListener("DOMContentLoaded", execHandler, false); 
		addEvent(window, "load", execHandler);
	}

	onready(init);

})();

