dojo.require("dijit.Tooltip");
dojo.require("dojo.parser");

function GlossaryTermHighlighter() {

	var ok = ((document.createElement) ? true : false);
	var terms = new Array();
	var foundCount = 0;
	var DEBUG = false;
	var elements;
	var alreadyUsed = new Array();

	if (!ok) return;

	/**
	 * the css elements that can contain glossary terms (use "body" for the entire page)
	 */
	this.setCSSQuery = function(cssQuery) {
	
		if (!ok) return;
		
		elements = dojo.query(cssQuery);
		
	}
	
	/**
	 * add a term to be highlighted
	 * term - the text
	 * termId - the id of an element that provides the rollover copy
	 */
	this.addTerm = function(term, termId) {
		if (!ok) return;
		terms.push(new GlossaryTerm(term, termId));
	}

	/** 
	 * highlight the terms on the page
	 */
	this.highlight = function() {
	
		if (!ok || elements.length == 0 || terms.length == 0) return;
		
		terms.sort(function(term1, term2){return(term2.term.length-term1.term.length)});
		var msg = "Available terms\n";
		for (var i = 0; i < terms.length; i++) {
			term = terms[i];
			for (var j=0; j < elements.length; j++) {
				this.highlightTerm(elements[j], term, true);
			}
			msg += term.term + " was" + (term.found ? " " : " not ") + " found\n";
		}

		if (DEBUG) alert(msg);

	}
	
	/** 
	 * get a list of all matching terms
	 */
	this.matching = function() {

		if (!ok || elements.length == 0 || terms.length == 0) return;

		var ret = new Array();
		terms.sort(function(term1, term2){return(term2.term.length-term1.term.length)});
		
		for (var i = 0; i < terms.length; i++) {
			term = terms[i];
			if (this.isAlreadyUsed(term)) continue;
			for (var j=0; j < elements.length; j++) {
				this.highlightTerm(elements[j], term, false);
			}
			if (term.found) ret.push(term);
		}

		return ret;
	}

	/**
	 *
	 */
	this.isAlreadyUsed = function(term) {
		for (var i=0; i<alreadyUsed.length; i++) {
			if (term.term == alreadyUsed.toLowerCase()) return true; 
		}
		return false;
	}

	/**	
	 * highlight a term within a given node
	 */
	this.highlightTerm = function(node, term, highlight) {
		// this little step is required to prevent IE from getting wrapped around the axle on 
		// certain types of malformed HTML.
		if (node.nodeType == 1) // element
		{
			if (node.getAttribute("sth_x") == term.term) return;
			else node.setAttribute("sth_x", term.term);
		}
		
		if (node.hasChildNodes())
		{
			for (var i = 0; i < node.childNodes.length; i++) 
			{
				this.highlightTerm(node.childNodes[i], term, highlight);
			}
		}

		if (node.nodeType == 3)
		{
			var p = node.parentNode;
			if (p.nodeName != 'TEXTAREA' && p.nodeName != 'SCRIPT' && p.className.substr(0, term.CSS_CLASS_PREFIX.length) != term.CSS_CLASS_PREFIX)
			{
				var result = term.pattern.exec(node.nodeValue);
				if (result != null)
				{
					term.found = true;
					foundCount++;
					var v = node.nodeValue;
					if (highlight) {
						var lt = document.createTextNode(v.substr(0, result.index));
						var rt = document.createTextNode(v.substr(result.index + result[0].length));
						var span = document.createElement('A');
						span.className = term.cssClass;
						span.id = term.termId + "-" + foundCount;
						span.href = "javascript:void(0);";
						span.appendChild(document.createTextNode(result[0]));
						p.insertBefore(lt, node);
						p.insertBefore(span, node);
						p.replaceChild(rt, node);
						new dijit.Tooltip({label:dojo.byId(term.termId).innerHTML, connectId:[span.id]});
					}
				}
			}
		}
	}

}

/**
 * create a glossary term object used for highlighting
 */
function GlossaryTerm(term, termId) {
	this.CSS_CLASS_PREFIX = 'sth_';
	this.term = term.toLowerCase();
	this.cssClass = this.CSS_CLASS_PREFIX + termId;
	this.termId = termId;
	this.pattern = new RegExp('\\b' + this.term + '\\b', 'i');
	this.found = false;
	this.toString = function(){return this.term};
}

