window.addEvent('domready',function(){

	/* instance */
	var highlighter = new Highlighter({
		elements: '.doglossaryhighlight p,.do-glosshighlight li, .doglossaryhighlight td, .doglossaryhighlight li',
		className: 'gloss-highlight',
		autoUnhighlight: false,
		onlyWords: true,
		definitions: glossaryDefArr,
		wordsArr: glossaryArr2
	});
	
	//$each(glossaryArr,function(item,index){
	//	highlighter.highlight(glossaryArr[index].word,glossaryArr[index].def);
    //});
    
    highlighter.highlight();
    
    
    $$('.cufon-canvas .gloss-highlight,.cufon-vml .gloss-highlight').each(function(el,index){
		el.getParent().getParent().addClass('gloss-highlight');
		el.getParent().getParent().set('rel',el.get('rel'));
	});
    
    //Tool tips for glossary
	var glossTips = new Tips('.gloss-highlight',{text:'rel',className:'gloss-tip'});
});


var Highlighter = new Class({
			
	/* implements */
	Implements: [Options],

	/* options */
	options: {
		autoUnhighlight: true,
		caseSensitive: false,
		elements: '*',
		className: '',
		onlyWords: false,
		tag: 'span',
		definitions: '',
		wordsArr: ''
	},
	
	/* initialization */
	initialize: function(options) {
		/* set options */
		this.setOptions(options);
		this.elements = $$(this.options.elements);
		this.words = [];
	},
	
	/* directs the plugin to highlight elements */
	highlight: function(elements,className) {
		
		words = this.options.wordsArr;
		
		/* figure out what we need to use as element(s) */
		var elements = $$(elements || this.elements);
		var klass = className || this.options.className;
		if (words.constructor === String) { words = [words]; }
		
		/* auto unhighlight old words? */
		if(this.options.autoUnhighlight) { this.unhighlight(); }
		
		/* set the pattern and regex */
		var pattern = '(' + words.join('|') + ')';
		
		//there is an optional "s" on the end of pattern for basic pural matching
		var pattern = this.options.onlyWords ? '\\b' + pattern + '[s]*\\b' : pattern ;//'(' + words.join('|') + ')';
		//console.log(pattern);
		var regex = new RegExp(pattern, this.options.caseSensitive ? '' : 'i');
		
		/* run it for each element! */
		elements.each(function(el) { this.recurse(el,regex,klass); },this);
		
		/* make me chainable! */
		return this;
	}, 
	
	/* unhighlights items */
	unhighlight: function(words) {
		//var selector = this.options.tag + (word ? '[rel=' + word + ']' : '');
		if (words.constructor === String) { words = [words]; }
		words.each(function(word) {
			word = (this.options.caseSensitive ? word : word.toUpperCase());
			if(this.words[word]) {
				var elements = $$(this.words[word]);
				elements.set('class','');
				elements.each(function(el) {
					var tn = document.createTextNode(el.get('text'));
					el.getParent().replaceChild(tn,el);
				});
			}
		},this);
		return this;
	},
	
	/* recursed function */
	recurse: function(node,regex,klass) {
		
			if (node.nodeType === 3) {
				var match = node.data.match(regex);
				if (match) {
					/* new element */
					var highlight = new Element(this.options.tag);
					highlight.addClass(klass);
					var wordNode = node.splitText(match.index);
					wordNode.splitText(match[0].length);
					var wordClone = wordNode.cloneNode(true);
					highlight.appendChild(wordClone);
					wordNode.parentNode.replaceChild(highlight, wordNode);
					//highlight.set('rel',highlight.get('text'));					
					//highlight.set('rel',def);
					var comparer = highlight.get('text');
					
					//to find the correct definition we need to see if we've matched with a plural ('s' on end only) or the original word
					//if the definition is undefined we remove one character from the end of the matched word and that should match a definition.
					if(this.options.definitions[this.options.wordsArr.indexOf(comparer.toUpperCase())] !== undefined){
						var definition = this.options.definitions[this.options.wordsArr.indexOf(comparer.toUpperCase())];
						//console.log('{' + comparer + ' ' + this.options.definitions[this.options.wordsArr.indexOf(comparer.toUpperCase())] + '}');
					}else{
						var definition = this.options.definitions[this.options.wordsArr.indexOf(comparer.substr(0,comparer.length-1).toUpperCase())];
						//console.log('{alternative - ' + comparer + ' ' + this.options.definitions[this.options.wordsArr.indexOf(comparer.substr(0,comparer.length-1).toUpperCase())] + '}');
					}
					highlight.set('rel',definition);
					//console.log(comparer + ' ' + this.options.wordsArr.indexOf(comparer.toUpperCase()));
					//console.log(this.options.wordsArr);
					//console.log(highlight.get('text'));
					if(!this.options.caseSensitive) { comparer = highlight.get('text').toUpperCase(); }
					if(!this.words[comparer]) { this.words[comparer] = []; }
					this.words[comparer].push(highlight);
					return 1;
				}
			} else if ((node.nodeType === 1 && node.childNodes) && !/(script|style)/i.test(node.tagName) && !(node.tagName === 'A') && !(node.tagName === 'H1') && !(node.tagName === 'H2') && !(node.tagName === 'H3') && !(node.tagName === 'H4') && !(node.tagName === this.options.tag.toUpperCase() && node.className === klass)) {
				for (var i = 0; i < node.childNodes.length; i++) {
					i += this.recurse(node.childNodes[i],regex,klass);
				}
			}
			return 0;
		}
	});

