/**
  * Handles correctable nbest
  */

//global variables others might want to access
var _correctionListExists = false;

var _correctionSpanNodes = new Array();

//handle the n-best confusion set generated by the server
//for user-correctable interaction
function genericHandleNbestConfusions(replyNode) {
	var candidates = replyNode.getElementsByTagName("nbest")[0].getElementsByTagName("candidate");
	_correctionSpanNodes = new Array();
	
	var spanNodes = new Array();
	var optionSpans = new Array();
	var flashActivateFns = new Array();
	 
	for(var j = 0; j < candidates.length; j++) {	
		var candidate = candidates[j];
		var tokens = candidate.childNodes;
		var spanNode = document.createElement("span");
		spanNodes[j] = spanNode;
		_correctionSpanNodes[j] = spanNode;
		spanNode.optionSpans = optionSpans;
		
		if (_inCar) {
			// in case the span nodes go too long, they will wrap over the map
			spanNode.style.backgroundColor = "#ffffff";
			spanNode.style.mozOpacity = 0.8;
		}
		
		var optionSpan = document.createElement("span");
		optionSpans[j] = optionSpan;
		optionSpan.spanNode = spanNode;
		setupDropDownOptionFeel(optionSpan, createActivateNbestConfusion(spanNode, j));		
						
		for(var i = 0; i < tokens.length; i++) {
			var token = tokens[i];
			var type = token.getAttribute("type");
			var word = token.getAttribute("word");
			var className = (type == "CLASS") ? token.getAttribute("className") : null;
			
			var tokenSpan = document.createElement("span");
			tokenSpan.tokenWord = word;
			
			tokenSpan.appendChild(document.createTextNode(word));
			spanNode.appendChild(tokenSpan);
		
			var optionTokenSpan = document.createElement("span");
			optionTokenSpan.appendChild(document.createTextNode(word));
			optionSpan.appendChild(optionTokenSpan);

			if(type == "CLASS") {
				tokenSpan.tokenClassName = className;
				tokenSpan.style.color = "#990033";
				optionTokenSpan.style.color = "#990033";
								
				if(token.childNodes && token.childNodes.length > 0) {
					var confusionsList = token.childNodes[0].childNodes;
					if(confusionsList.length > 1) { //don't bother if no alternatives
						var small_drop_down = document.createElement("img");
						small_drop_down.src = "generic/sls/resources/small_dropdown.gif";
						tokenSpan.appendChild(small_drop_down);
						tokenSpan.style.textDecoration = "underline";				
						tokenSpan.style.cursor = "pointer";
										
						var toolTipFn  = createToolTipFunction(spanNode, tokenSpan,confusionsList, j, i);
						
						tokenSpan.toolTipFn = toolTipFn;
						tokenSpan.onmouseover = toolTipFn;
						if(j == 0) { //we will flash the top candidate confusions quickly
							flashActivateFns.push(toolTipFn);					
						}	
		   			}
				}
			} else {
				tokenSpan.style.color = "black";
			}	
				
			spanNode.appendChild(document.createTextNode(" "));
			optionSpan.appendChild(document.createTextNode(" "));
		}
		
		if(candidates.length > 0) {	
			makeSpanDropDown(spanNode, createNbestDropDown);
		}
		
		//add the send button
		var sendButton = document.createElement("input");
		sendButton.type = "submit";
		sendButton.value = "Send";
		sendButton.disabled = false; //alexgru: 2009-03-26, always allow it now
		sendButton.onclick = sendCorrectedRecResults;
		sendButton.title = "Send corrected input";
		sendButton.style.marginLeft = "5px";
		spanNode.appendChild(sendButton);
		spanNode.sendButton = sendButton;
	}
	
	if(spanNodes.length > 0) {
		activateNbestConfusion(spanNodes[0]);		
	} else {
		clearNbestConfusions();
	}
	
	//popup momentarily any options
	for(i = 0; i < flashActivateFns.length; i++) {
		_keepToolTipsOpen = true;
		flashActivateFns[i]();		
	}

	if(_keepToolTipsOpen) {
		setTimeout(function() { _keepToolTipsOpen=false; checkToolTips(_mouseX, _mouseY); }, 1200);
	}
}


function sendCorrectedRecResults() {
	for(var i = 0; i < _correctionSpanNodes.length; i++) {
		_correctionSpanNodes[i].sendButton.disabled = false; //alexgru 2009-03-26, no longer disable
	}

	if (_isPlaying) {
		abortAudio(); // turn off the speech of the computer
	}

	var spanNode = document.getElementById("RecResultsSpan");

	var str = "";

	var optSpace = "";
	if(spanNode && spanNode.childNodes) {
		for(var i = 0; i < spanNode.childNodes.length; i++) {
			var node = spanNode.childNodes[i];
			if(node.tagName && node.tagName.toLowerCase() == "span") {
				var tokenSpan = node;
				var className = tokenSpan.tokenClassName;
				var word = tokenSpan.tokenWord;
	
				if(className != null && isNaN(parseInt(className))) {
					str += optSpace + "<$" + className + "> " + word + " </$" + className + ">";
				} else { 
					str += optSpace + word;
				}
				
				if(optSpace == "") optSpace = " ";
			}
		}
	}
	
	sendNL(str, true);
	
}

//used to activate a particular nbest confusion entry
//picked from the dropdown list
function activateNbestConfusion(spanNode) {
	var oldSpanNode = document.getElementById("RecResultsSpan");

	if(oldSpanNode != null) {
		oldSpanNode.id = null;	
	}

	spanNode.id = "RecResultsSpan";
	updateCorrectableRecResults(spanNode);
	spokenRequest = true;
	correctionListExists = true;
}

function createActivateNbestConfusion(spanNode, candidateIndex) {
	return function() {
		var dropdown = document.getElementById("NbestDropDown");
		if(dropdown != null) {
			removeDropDown(dropdown);
		}
		
		/*
		if(_isPlaying) {
			_madeCorrectionWhilePlaying = true; //defer sendbutton activiation
		} else {
			spanNode.sendButton.disabled = false;
		}
		*/
		activateNbestConfusion(spanNode);
		sendFrame('{c gui :user_model_update 1 :update {q update :candidate_replaced 1 :candidate_index ' + candidateIndex + ' }}');		
		
	}
}

function createNbestDropDown(e) {
	if(!_toolTipsEnabled) return;
	
	if(!e) e = window.event;
	var target = getTarget(e);

	if(document.getElementById("NbestDropDown")) {
		return document.getElementById("NbestDropDown"); //already created
	}

	var spanNode = getTarget(e).parentNode;	
	var dropdownDiv = createDropDownDiv(spanNode, spanNode.optionSpans);
	dropdownDiv.id = "NbestDropDown";

	dropdownDiv.onmouseover = function () { 
		if(_galaxyHandlers && _galaxyHandlers.nbestDropDownActivated) _galaxyHandlers.nbestDropDownActivated;	
	};
	//dropdownDiv.onmouseout = closeHelpAssistant("correctionHelp");

	if(e) {
		if(e.stopPropagation) e.stopPropagation();
		else e.cancelBubble = true;	
	}
	return dropdownDiv;
}


/**
 * creates a tooltip type function for choosing a different word from a confusion list
 */
function createToolTipFunction(spanNode, tokenSpan, confusionsList, candidateIndex, tokenIndex) {
	var tooltipDiv = document.createElement("div");
	tooltipDiv.tokenSpan = tokenSpan;

	
	for(var i = 0; i < confusionsList.length; i++) {

		if (_inCar) { // SEAN ADD
			if (i > 9) {
				break;
			}
		}

		var token = confusionsList[i];

		var wordSpan = document.createElement("span");							
		//wordSpan.style.textDecoration = "underline";				
		wordSpan.style.cursor = "pointer";
		
		var replaceTokenFn = createReplaceTokenFunction(token.getAttribute("word"), token.getAttribute("className"), tokenSpan, tooltipDiv, wordSpan, spanNode, candidateIndex, tokenIndex);
		var highlightWordFn = createHighlightGreen(wordSpan);
		var unhighlightWordFn = createUnHighlight(wordSpan);
		if(wordSpan.addEventListener) {		
				wordSpan.addEventListener("click", replaceTokenFn, true);
				wordSpan.addEventListener("mouseover", highlightWordFn, true);
				wordSpan.addEventListener("mouseout", unhighlightWordFn, true);
		} else if(wordSpan.attachEvent) {  // IE 5+  	
	    		wordSpan.attachEvent("onclick", replaceTokenFn);
	    		wordSpan.attachEvent("onmouseover", highlightWordFn);
	    		wordSpan.attachEvent("onmouseout", unhighlightWordFn);
	    } else {  //IE 4 
	    		wordSpan.onclick = replaceTokenFn;
	    		wordSpan.onmouseover = highlightWordFn;
	    		wordSpan.onmouseout = unhighlightWordFn;
	   	}
	   	
	   	wordSpan.highlightWordFn = highlightWordFn;
	   	wordSpan.unhighlightWordFn = unhighlightWordFn;
	   	wordSpan.replaceTokenFn = replaceTokenFn;
		
		var wordNode = document.createTextNode(token.getAttribute("word"));		
		wordSpan.appendChild(wordNode);
		
		/*				
		var classSpan = document.createElement("span");	
		//classSpan.style.color = "grey";
		var classNameNode = document.createTextNode("[" + token.getAttribute("className").toLowerCase() + "]");
		classSpan.appendChild(classNameNode);
		*/
		tooltipDiv.appendChild(wordSpan);
		tooltipDiv.appendChild(document.createElement("br"));
		
		tooltipDiv.onmouseover = function () { 
			if(_galaxyHandlers && _galaxyHandlers.nbestTokenDropDownActivated) 
				_galaxyHandlers.nbestTokenDropDownActivated();	
		};
		//tooltipDiv.onmouseout = closeHelpAssistant("correctionHelp");
		
	}

	tooltipDiv.className = "CorrectionTooltip";
	
	
	return function(e) {
		if(!e) e = window.event;
		
		if(!_toolTipsEnabled) return;
  	 	var body = document.getElementsByTagName("body")[0]
		if(!tokenSpan.tooltipDiv) {
			body.appendChild(tooltipDiv);
			tokenSpan.tooltipDiv = tooltipDiv;
		}
		  	 	
		//x,y based on token span
		var rect = getBoundingRect(tokenSpan);
		var padding = 2;
  	 	tooltipDiv.style.left = (rect.left - padding) + "px";
  	 	tooltipDiv.style.top = (rect.top + rect.height) + "px";
  	
		if (e) {
			if(e.stopPropagation) e.stopPropagation();
			else e.cancelBubble = true;	
		}
		
		return tooltipDiv;
	}	
}

function createReplaceTokenFunction(word, className, tokenSpan, tooltipDiv, wordSpan, spanNode, candidateIndex, tokenIndex) {
	return function(e) {
		tokenSpan.removeChild(tokenSpan.childNodes[0]);
		tokenSpan.insertBefore(document.createTextNode(word), tokenSpan.childNodes[0]);
		tokenSpan.tokenClassName = className;
		tokenSpan.tokenWord = word;
		
		wordSpan.style.backgroundColor = "";
		if(tokenSpan.tooltipDiv) {
			document.getElementsByTagName("body")[0].removeChild(tokenSpan.tooltipDiv);
			tokenSpan.tooltipDiv = null;
		}
		
		/*
		if(_isPlaying) {
			_madeCorrectionWhilePlaying = true; //defer sendbutton activiation
		} else {
			spanNode.sendButton.disabled = false;
		}
		*/
		
		sendFrame('{c gui :user_model_update 1 :update {q update :token_replaced 1 :candidate_index ' + candidateIndex + ' :token_index ' + tokenIndex + ' :word "' + word + '" :class_name "' + className + '" }}');		
	}
}

var _keepToolTipsOpen = false;

/** 
 * closes any tooltips or dropdowns which are open but which the mouse
 * is no longer over
 */
function checkToolTips(x, y) {
    if(_keepToolTipsOpen && x != -1 && y != -1 && _toolTipsEnabled) {
    	return;
    }		
	var recResults = document.getElementById("RecResultsSpan");	
	if(recResults != null && recResults.childNodes && recResults.childNodes.length > 0) {	
	
		var body = document.getElementsByTagName("body")[0];
		for(var i = 0; i < recResults.childNodes.length; i++) {
			var tokenSpan = recResults.childNodes[i];
			
			if(tokenSpan.tooltipDiv) {
				var	rect1 = getBoundingRect(tokenSpan);
				var rect2 = getBoundingRect(tokenSpan.tooltipDiv);
				
				if(!rectContains(rect1,x,y) && !rectContains(rect2, x,y)) {			
					body.removeChild(tokenSpan.tooltipDiv);
					tokenSpan.tooltipDiv = null;
				}  		 	
			}
		}
	
		//now check the dropdown	
		var dropdown = document.getElementById("NbestDropDown");
		if(dropdown != null) {
			var dropdownRect = getBoundingRect(dropdown);
			var recResultsRect = getBoundingRect(recResults);
			
			if(!rectContains(dropdownRect,x,y) && !rectContains(recResultsRect,x,y)) {
				removeDropDown(dropdown);
			}
		}		
	}
}

function clearNbestConfusions() {
	_correctionListExists = false;
	updateCorrectableRecResults(document.createElement("span"));
}

//for now just a string, but much more to come
function updateRecResults(nlString) {
	var spanNode = document.createElement("span");
	spanNode.appendChild(document.createTextNode(nlString));
	updateCorrectableRecResults(spanNode);
}

var _toolTipsEnabled = true;
function updateCorrectableRecResults(spanNode) {
	_toolTipsEnabled = false;
	checkToolTips(-1,-1); //get rid of anything open..
	var div = document.getElementById("RecResults");
	
	while(div.childNodes != null && div.childNodes.length > 0) {
		div.removeChild(div.childNodes[0]);
	}
	div.appendChild(spanNode);

	div.onmouseover = function () { 
		if(_galaxyHandlers && _galaxyHandlers.newNbest) _galaxyHandlers.newNbest();
	};
	_toolTipsEnabled = true;
	//div.onmouseout = closeHelpAssistant("correctionHelp");
}

