// Depends on XML
// Depends on Utils
// Depends on YAHOO Dom

var EOIR = EOIR ? EOIR : function ()
{
	var obj =
	{
	};

	return obj;
} ();

EOIR.Glossary = function (fnLoaded, strGlossaryFile)
{
	this.m_xml = null;
	this.m_hideDelayTimer = null;

	this.m_elem = null;
	this.m_elemLabel = null;

	this._load = function (strGlossaryFile, fnLoaded)
	{
		if(strGlossaryFile == null)
		{
			strGlossaryFile = EOIR.Glossary.getGlossaryFile();
		}

		if(this.m_xml == null)
		{
			// There's a problem with this. If we're changing instructor codes, then the cached config is no longer
			// valid. Need to rework this.
			//			this.m_xml = EOIR.Utils.getProperty("xmlconfig");
			if(this.m_xml == null)
			{
				var wnd = EOIR.Utils.getMainWindow();
				if(window != wnd && wnd != null && wnd.EOIR.Glossary != null)
				{
					// Force the config to always be loaded in the main window
					// if possible. This is to allow the caching to work properly
					// on some browsers (Firefox) that like to garbage collect
					// objects when the page that creates the objects exits.
					return wnd.EOIR.Glossary.get(fnLoaded);
				}
				else
				{
					if(EOIR.Utils.isWebBased() && !EOIR.Utils.isSCORMCompliant())
					{
						this.m_xml = EOIR.Glossary._requestGlossaryFile(strGlossaryFile, fnLoaded, this);
						//if((fnLoaded != undefined) && (fnLoaded != null))
						//{
						//    fnLoaded(this);
						//}

						/*
						var xmlhttp = new XMLHttpRequest();
						xmlhttp.open("GET", strGlossaryFile);
            																									
						xmlhttp.onreadystatechange = function()
						{
						if(xmlhttp.readyState == 4)
						{
						if(xmlhttp.status == 200)
						{
						g_glossary.m_xml = xmlhttp.responseXML;
						if(fnLoaded != null)
						{
						fnLoaded(g_glossary);
						}
						}
						}
						};
						xmlhttp.send(null);*/
					}
					else
					{
						//						this.m_xml = EOIR.XML.createObject();
						try
						{
							var that = this;

							var fnXMLLoaded = (fnLoaded != null) ? function (xml)
							{
								that.m_xml = xml;
								fnLoaded(that);
							} : null;

							var xml = EOIR.XML.load(strGlossaryFile, fnLoaded != null, fnXMLLoaded, null, null);
							if(fnLoaded == null)
							{
								this.m_xml = xml;
							}
						}
						catch(e)
						{
							this.m_xml = null;
							throw e;
						}
					}

				}

				if((fnLoaded == undefined) || (fnLoaded == null)) //if fnLoaded exists, we dont expect the xml to be loaded yet
				{
					if(this.m_xml == null)
					{
						alert("Could not load glossary file1: " + strGlossaryFile);
					}
				}
			}
			else
			{
				if((fnLoaded != undefined) && (fnLoaded != null))
				{
					fnLoaded(this);
				}
			}
		}
		else
		{
			if((fnLoaded != undefined) && (fnLoaded != null))
			{
				fnLoaded(this);
			}
		}

		// Return ourselves if we're the main window or if that window
		// doesn't exist.	
		return this;
	};

	this.getXMLDocument = function ()
	{
		return this.m_xml;
	}

	this.isValid = function ()
	{
		return this.m_xml != null;
	}

	this.getDefinition = function (strTerm)
	{
		var nodes = this.m_xml.selectNodes("glossary/term[@name=\"" + strTerm + "\"]");
		if(nodes != null && nodes.length > 0)
		{
			return nodes[0].getAttribute("definition");
		}
	}

	this.showDefinition = function (evt)
	{
		var elemSrc = YAHOO.util.Event.getTarget(evt);

		if(elemSrc.className == "Glossary")
		{
			this.cancelHideDelay();

			var strTerm = elemSrc.getAttribute("term");
			if(strTerm == null)
			{
				strTerm = elemSrc.innerHTML;
			}
			strTerm = strTerm.toLowerCase();

			if(this.m_elem != null && this.m_elemLabel != null)
			{
				if(this.m_elem.style.display == "block" && this.m_elem.getAttribute("term") == strTerm)// we don't want to shift around the tooltip if the mouse moves
				{
					return;
				}

				var nAvailHeight = this.m_elem.ownerDocument.body.parentNode.clientHeight != 0 ? this.m_elem.ownerDocument.body.parentNode.clientHeight : 768;
				var nAvailWidth = this.m_elem.ownerDocument.body.parentNode.clientWidth != 0 ? this.m_elem.ownerDocument.body.parentNode.clientWidth : 1024;

				this.m_elem.setAttribute("term", strTerm);
				this.m_elemLabel.innerHTML = this.getDefinition(strTerm);

				var nWidthDesired = Math.min(400, Math.max(100, nAvailWidth - YAHOO.util.Event.getPageX(evt) - 10));
				this.m_elem.style.left = Math.max(0, Math.min(YAHOO.util.Event.getPageX(evt), nAvailWidth - nWidthDesired - 10)) + "px";
				this.m_elem.style.maxWidth = nWidthDesired + "px";
				this.m_elem.style.display = "block";

				// try to position it below the word
				var nElemSrcTop = getElemAbsoluteTopPos(elemSrc);
				var nTopDesired = Math.max(nElemSrcTop + elemSrc.offsetHeight, YAHOO.util.Event.getPageY(evt));
				if(nTopDesired + this.m_elem.clientHeight > nAvailHeight)
				{
					// if there's not enough space move it above
					nTopDesired = Math.max(0, nElemSrcTop - this.m_elem.clientHeight);
				}
				this.m_elem.style.top = nTopDesired + "px";

			}
		}
	}

	this.hideDefinition = function (evt)
	{
		this.hideDelay();
	}

	this.cancelHideDelay = function ()
	{
		if(this.m_hideDelayTimer != null)
			this.m_hideDelayTimer.cancel();
	}

	this.hideDelay = function ()
	{
		this.cancelHideDelay();
		this.m_hideDelayTimer = YAHOO.lang.later(250, this, function ()
		{

			if(this.m_elem != null)
			{
				this.m_elem.setAttribute("term", null);
				this.m_elem.style.display = "none";
			}

			//$("ttDefinition").setAttribute("term", null);
			//$("ttDefinition").style.display = "none";

		});
	}
	
	this.update = function (elem)
	{
	    if(elem == null || elem.ownerDocument == null)
		{
		    return;
		}
		else
		{
		    if(this.m_elem == null || this.m_elemLabel == null)
		    {
		        this.initDocument(elem.ownerDocument);		
		    }
		    else
		    {
		        //if(!YAHOO.util.Dom.hasClass("Glossary"))
		        //{
		        //    YAHOO.util.Dom.addClass(elem, "Glossary");
		        //}
		        var arrGlossaryElems = YAHOO.util.Dom.getElementsByClassName("Glossary", "span", elem);
		        for(var i = 0; i < arrGlossaryElems.length; i++)
		        {
			        YAHOO.util.Event.addListener(arrGlossaryElems[i], "mouseover", this.showDefinition, this, this);
			        YAHOO.util.Event.addListener(arrGlossaryElems[i], "mouseout", this.hideDefinition, this, this);
			        arrGlossaryElems[i].title = "";
		        }
			}			
		}
	}

	this.initDocument = function (docElem)
	{
		this.m_elem = null;
		this.m_elemLabel = null;

		if(docElem == null)
		{
			docElem = window.document;
		}

		var arrGlossaryElems = YAHOO.util.Dom.getElementsByClassName("Glossary", "span", docElem.body);
		for(var i = 0; i < arrGlossaryElems.length; i++)
		{
			YAHOO.util.Event.addListener(arrGlossaryElems[i], "mouseover", this.showDefinition, this, this);
			YAHOO.util.Event.addListener(arrGlossaryElems[i], "mouseout", this.hideDefinition, this, this);
			arrGlossaryElems[i].title = "";
		}

		if(arrGlossaryElems.length > 0)
		{
			var ttDefinition = docElem.getElementById("ttDefinition");
			if(ttDefinition == null)
			{
				ttDefinition = docElem.createElement("div");
				ttDefinition.id = "ttDefinition";
				ttDefinition.className = "GlossaryTooltip";
				ttDefinition.style.display = "none";
				ttDefinition.style.position = "absolute";
				ttDefinition.style.zIndex = 1000;
				ttDefinition.style.borderRight = "black 1px solid";
				ttDefinition.style.borderTop = "black 1px solid";
				ttDefinition.style.borderLeft = "black 1px solid";
				ttDefinition.style.borderBottom = "black 1px solid";
				ttDefinition.style.backgroundColor = "infobackground";
				ttDefinition.style.padding = "5px 5px 5px 5px";
				ttDefinition.style.color = "infotext";
				ttDefinition.style.left = "0px";
				ttDefinition.style.top = "0px";
				ttDefinition.innerHTML = "<span id='ttDefinitionLabel' style='font-size:11px;'>Hello</span>";
				docElem.body.appendChild(ttDefinition);
			}

			this.m_elem = ttDefinition;
			this.m_elemLabel = ttDefinition.firstChild;
		}
	}

	// May return the current Glossary object or the one from the main window.
	return this._load(strGlossaryFile, fnLoaded);
}

function getElemAbsoluteLeftPos(elem)
{
	if(elem.offsetParent == null)
	{
		return 0;
	}
	else
	{
	    var value = getElemAbsoluteLeftPos(elem.offsetParent);
		return  value + elem.offsetLeft;
	}
}
		
function getElemAbsoluteTopPos(elem)
{
	if(elem.offsetParent == null)
	{
		return 0;
	}
	else
	{
	    var value = getElemAbsoluteTopPos(elem.offsetParent);
		return value + elem.offsetTop;
	}
}


EOIR.Glossary.get = function(fnLoaded, strGlossaryFile)
{
	return new EOIR.Glossary(fnLoaded, strGlossaryFile);
}


//so this function will get the glossary file from the server synchronously if fnLoaded is null;
//   otherwise it will run asynchronously and call fnLoaded when done
var g_glossary = null;
EOIR.Glossary._requestGlossaryFile = function (strGlossaryFile, fnLoaded, objGlossary)
{
	if(EOIR.Utils.isWebBased())
	{
		try
		{
		    var isSync = ((fnLoaded != undefined) && (fnLoaded != null));
		
		    // definitely doesn't work -- need to take another look at this!
			var xmlhttp = new XMLHttpRequest();
	        xmlhttp.open("GET", strGlossaryFile, isSync); //FALSE HERE RUNS REQUEST SYNCHRONOUSLY
	        			 
	        if(isSync)
	        {      
	            g_glossary = objGlossary;
	             
	            xmlhttp.onreadystatechange = function()
			        {
			            if(xmlhttp.readyState == 4)
			            {
			                if(xmlhttp.status == 200)
			                {
			                    g_glossary.m_xml = xmlhttp.responseXML;
				                
				                fnLoaded(g_glossary);
				                
				                return;
			                }
			            }
			            alert("Failed to load glossary file asynchronously!");
			        };
			}
			    
			xmlhttp.send(null);
			
	        if(xmlhttp.status == 200)
	        {
	            return xmlhttp.responseXML;
	        }
		}
		catch(e)
		{
			// This is just in case the XMLHttpRequest object doesn't work.
		}
	}

	return EOIR.XML.load(strGlossaryFile, false);
};

EOIR.Glossary.getGlossaryFile = function ()
{
	try
	{
		if(!EOIR.Utils.isInROCBrowser())
		{
			return EOIR.Utils.getAbsolutePath("/config/glossary.xml");
		}
		else
		{
			var strGlossaryFile = EOIR.Utils.getPropertySetEvalDefault("GlossaryFile", "getExternal().GlossaryFilename");
			if(strGlossaryFile != null)
			{
				return strGlossaryFile;
			}
		}
	}
	catch(e)
	{
		//alert("getGlossaryFile error: " + e.message);
	}

	return EOIR.Utils.getAbsolutePath("/config/glossary.xml");		
}

