/*
Program:
Husky Mounted Detection System (HMDS)

Source:
EOIR Technologies
PO Box 1240
Spotsylvania, VA  22553

HMDS Development Team
USA CECOM Night Vision and Electronic Sensors Directorate (NVESD)
10221 Burbeck Rd., STE 430
Fort Belvoir, VA 22060

Conditions for Use:
This software is Copyright(C) EOIR Technologies, Inc.

EOIR Technologies has all commercial interest and rights.
NVESD has full rights, title, and interest.

This software is provided "as is", without warranty by 
EOIR Technologies, Inc and NVESD. In no event shall EOIR 
Technologies, Inc. or NVESD be liable for any loss or for
any indirect, special, punitive, exemplary, incidental, or 
consequential damages arising from the use, possession, or
performance of this software.
*/

// Depends on XML
// Depends on Utils

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

	return obj;
} ();

function decodeAttribute(str)
{
	return (str == "null") ? null : str;
}

EOIR.User = function(strID, strName, strNumber)
{
	this.ID = strID != null ? strID.toLowerCase() : null;
	this.Name = strName;
	this.Number = strNumber;
	this.Scores = {};

	this.toString = function()
	{
		return this.Name + " " + this.Number;
	}

	this.serialize = function()
	{
		var strAttribs = "";
		for(var strKey in this)
		{
			if(typeof (this[strKey]) != "function")
			{
				strAttribs += strKey.toLowerCase() + "='" + this[strKey] + "' ";
			}
		}

		var str = "<user " + strAttribs + " />";
		return str;
	}

	this.getUserAttributesFromNode = function(node)
	{
		if(node == null)
		{
			return null;
		}
		else
		{
			for(var i = 0; i < node.attributes.length; i++)
			{
				var strAttribName = node.attributes[i].name;

				// This part matches up the attributes with user properties.
				// This needs to be done since the attributes in the XML file are lower case
				// and the properties in the User Object not.
				var strUserProp = null;
				for(var strPropName in this)
				{
					if(strPropName.toLowerCase() == strAttribName)
					{
						strUserProp = strPropName;
						break;
					}
				}

				if(strUserProp == null)
				{
					strUserProp = strAttribName;
				}

				var strVal = node.attributes[i].nodeValue;
				if(strVal == "null")
				{
					strVal = null;
				}

				this[strUserProp] = strVal;
			}
		}
	}

	this.getUserInfo = function()
	{
		try
		{
			var xmlUser = EOIR.User.getUserXMLFromId(this.ID);
			if(xmlUser != null)
			{
				this.getUserAttributesFromNode(xmlUser);
			}
		}
		catch(e)
		{
		}
	}

	this.getProperty = function(strProp, strDefault)
	{
		var prop = this[strProp];
		if(prop == null)
		{
			return strDefault;
		}

		return prop;
	}

	this.setProperty = function(strProp, val)
	{
		this[strProp] = val;
	}

	this.clearProperty = function(strProp)
	{
		this[strProp] = null;

		try { delete this[strProp]; } catch(e) { }
	}

	this.getTestNode = function(strSetId, strType, strSubType, bCreate)
	{
		var xmlUser = EOIR.User.getUserXMLFromId(this.ID);
		if(xmlUser != null)
		{
			var nodeTests = xmlUser.selectSingleNode("tests");
			if(nodeTests == null && bCreate)
			{
				nodeTests = xmlUser.ownerDocument.createElement("tests");
				xmlUser.appendChild(nodeTests);
			}

			if(nodeTests != null)
			{
				var nodeTest = nodeTests.selectSingleNode("test[@set='" + strSetId + "' and @type='" + strType + "' and @subtype='" + strSubType + "']");
				if(nodeTest == null && bCreate)
				{
					nodeTest = xmlUser.ownerDocument.createElement("test");
					nodeTest.setAttribute("set", strSetId);
					nodeTest.setAttribute("type", strType);
					nodeTest.setAttribute("subtype", strSubType);
					nodeTests.appendChild(nodeTest);
				}

				return nodeTest;
			}
		}

		return null;
	}

	this.hasScore = function(strSetId, strTestType, strTgtType)
	{
		//		return this.getProperty(strTgtType + strTestType + "score_" + strSetId, null) != null;
		var nodeTest = this.getTestNode(strSetId, strTestType, strTgtType, false);
		var bHasScore = !(nodeTest == null || isNaN(parseFloat(nodeTest.getAttribute("score"))));
		if(!bHasScore)
		{
			try
			{
				bHasScore = (this.Scores[strSetId + "|" + strTestType + "|" + strTgtType] != null);
			}
			catch(e) { }
		}
		return bHasScore;
	}

	this.getScore = function(strSetId, strTestType, strTgtType)
	{
		//		return parseFloat(this.getProperty(strTgtType + strTestType + "score_" + strSetId, 0));

		try
		{
			var nodeTest = this.getTestNode(strSetId, strTestType, strTgtType, false);
			if(nodeTest != null)
			{
				var score = parseFloat(nodeTest.getAttribute("score"));
				if(!isNaN(score))
				{
					return score;
				}
			}

			var fScore = this.Scores[strSetId + "|" + strTestType + "|" + strTgtType];
			return fScore != null ? fScore : 0;
		}
		catch(e) { return 0; }

	}

	this.getScoreDate = function(strSetId, strTestType, strTgtType)
	{
		var nodeTest = this.getTestNode(strSetId, strTestType, strTgtType, false);
		if(nodeTest != null)
		{
			try
			{
				return new Date(Date.parse(nodeTest.getAttribute("date")));
			}
			catch(e) { }

		}
		//		return this.getProperty(strTgtType + strTestType + "date_" + strSetId, null);
	}

	this.setScore = function(strSetId, strTestType, strTgtType, fScore)
	{
		try
		{
			this.Scores[strSetId + "|" + strTestType + "|" + strTgtType] = fScore;
		} catch(e) { alert(e.description); };

		var nodeTest = this.getTestNode(strSetId, strTestType, strTgtType, true);
		if(nodeTest != null)
		{
			nodeTest.setAttribute("score", fScore);
			nodeTest.setAttribute("date", new Date().toString());

			// This twiddles w/ the XML nodes directly.
			// DON'T CALL UPDATE HERE. That reloads the XML that we've messed with.
			// Just save the XML.
			//	this.update();

			try
			{
				this._updateXML(nodeTest.parentNode.parentNode);
			}
			catch(e) { }
		}
	}

	this._getConfInfoProperty = function(strName, defaultVal)
	{
		var strId = EOIR.Config.getCurrentTargetSetId();
		if(EOIR.Utils.parseBool(this.getProperty("usecustomset")))
		{
			strId += "_custom";
		}

		return parseInt(this.getProperty(strName + "_" + strId, defaultVal));
	}

	this._setConfInfoProperty = function(strName, num)
	{
		var strId = EOIR.Config.getCurrentTargetSetId();
		if(EOIR.Utils.parseBool(this.getProperty("usecustomset")))
		{
			strId += "_custom";
		}

		return this.setProperty(strName + "_" + strId, num);
	}

	this.getConfSetNum = function()
	{
		return this._getConfInfoProperty("confsetnum", 0);
	}

	this.getTgtIndex = function()
	{
		return this._getConfInfoProperty("cstgtnum", 0);
	}

	this.getMaxConfSetNum = function()
	{
		return this._getConfInfoProperty("maxsetnum", -1);
	}

	this.getMaxTgtNum = function()
	{
		return this._getConfInfoProperty("maxtgtnum", -1);
	}

	this.setConfSetNum = function(num)
	{
		return this._setConfInfoProperty("confsetnum", num);
	}

	this.setTgtIndex = function(num)
	{
		return this._setConfInfoProperty("cstgtnum", num);
	}

	this.setMaxConfSetNum = function(num)
	{
		return this._setConfInfoProperty("maxsetnum", num);
	}

	this.setMaxTgtNum = function(num)
	{
		return this._setConfInfoProperty("maxtgtnum", num);
	}

	this._updateXML = function(xml)
	{
		if(EOIR.Utils.isWebBased())
		{
			EOIR.User.updateXML(this.ID, EOIR.XML.serializeChildren(xml));
		}
		else
		{
			EOIR.Utils.writeXMLFile(xml.ownerDocument, EOIR.User.getUserInfoFile());
		}

	}

	this.update = function()
	{
		if(!EOIR.User.isDemoUser(this))
		{
			if(!EOIR.Utils.isSCORMCompliant())
			{
				var xmlUser = EOIR.User.getUserXMLFromId(this.ID);
				if(xmlUser == null)
				{
					// Need to create a new node.
					var docUsers = EOIR.User.loadUserFile();
					if(docUsers != null)
					{
						xmlUser = docUsers.createElement("user");
						docUsers.documentElement.appendChild(xmlUser);
					}
				}

				for(var strProp in this)
				{
					var type = typeof this[strProp];
					if(type != "function" && type != "object")
					{
						var strPropLower = strProp.toLowerCase();
						if(this[strProp] == null)
						{
							xmlUser.removeAttribute(strPropLower);
						}
						else
						{
							xmlUser.setAttribute(strPropLower, this[strProp]);
						}
					}
				}

				// We need to remove any attributes that are not part of the user object.
				for(var i = 0; i < xmlUser.attributes.length; i++)
				{
					var strAttribName = xmlUser.attributes[i].name;

					// This part matches up the attributes with user properties.
					// This needs to be done since the attributes in the XML file are lower case
					// and the properties in the User Object not.
					var strUserProp = null;
					for(var strPropName in this)
					{
						if(strPropName.toLowerCase() == strAttribName)
						{
							strUserProp = strPropName;
							break;
						}
					}

					if(strUserProp == null)
					{
						xmlUser.removeAttribute(strAttribName);
					}
				}

				this._updateXML(xmlUser);
			}
			else
			{
				throw "Not implemented - update SCORM";
				/*try
				{
				var htSCORMSuspendInfo = getSCORMSuspendInfo();
    				
				if(user.vehicleset != null)
				{
				htSCORMSuspendInfo["vset"] = user.vehicleset;
				}
    				
				if(user.thermalpretestscore != null)
				{
				htSCORMSuspendInfo["tpret"] = user.thermalpretestscore;
				}
				if(user.thermalposttestscore != null)
				{
				htSCORMSuspendInfo["tpostt"] = user.thermalposttestscore;
				}
				if(user.visiblepretestscore != null)
				{
				htSCORMSuspendInfo["vpret"] = user.visiblepretestscore;
				}
				if(user.visibleposttestscore != null)
				{
				htSCORMSuspendInfo["vpostt"] = user.visibleposttestscore;
				}
    				
				if(user.confsetnum != null)
				{
				htSCORMSuspendInfo["csn"] = user.confsetnum;
				}
				if(user.cstgtnum != null)
				{
				htSCORMSuspendInfo["cstn"] = user.cstgtnum;
				}
    				
				setSCORMSuspendInfo(htSCORMSuspendInfo);			
				}
				catch(e)
				{
				}*/
			}
		}
	}

	this.toString = function()
	{
		return this.Name + "  (" + this.ID + ")";
	}
}

EOIR.User.deserialize = function(str)
{
	try
	{
		var parser = new DOMParser();
		var doc = parser.parseFromString(str);
		
		if(doc != null)
		{
			doc.setProperty("SelectionLanguage", "XPath");

			var user = new EOIR.User(decodeAttribute(doc.documentElement.getAttribute("id")), 
							decodeAttribute(doc.documentElement.getAttribute("name")),
							decodeAttribute(doc.documentElement.getAttribute("number")));

			user.getUserAttributesFromNode(doc.documentElement);										
			return user;
		}
	}
	catch(e)
	{
	}
	
	return null;
}

EOIR.User.User_Sorter = function(arg1, arg2)
{
	if(arg1.ID < arg2.ID) 
	{ 
		return -1; 
	} 
	else if(arg1.ID == arg2.ID) 
	{ 
		return 0; 
	} 
	else 
	{ 
		return 1; 
	} 
}

EOIR.User.loadUserFile = function(strCfgCode)
{
	var strFilename = EOIR.User.getUserInfoFile(strCfgCode);

	// This prevents caching on the server or client.
	if(EOIR.Utils.isWebBased())
	{
		strFilename += "?time=" + new Date().getTime();
	}
	return EOIR.User.loadUserFileByName(strFilename);
}

EOIR.User.loadUserFileByName = function(strFile)
{
	var xmlUsers = EOIR.XML.createObject();

	try
	{
		EOIR.XML.loadDocument(xmlUsers, strFile);
	}
	catch(e)
	{
		xmlUsers = null;
	}

	if(xmlUsers == null)
	{
		var parser = new DOMParser();
		xmlUsers = parser.parseFromString("<users></users>", "text/xml");
		xmlUsers.setProperty("SelectionLanguage", "XPath");
	}

	return xmlUsers;
}

EOIR.User.getUserListSorted = function(strCfgCode)
{
	var arrUsers = EOIR.User.getUserList(strCfgCode);
	if(arrUsers != null)
	{
		return arrUsers.sort(EOIR.User.User_Sorter);
	}
	
	return null;
}

EOIR.User.getUserList = function(strCfgCode)
{
	var xmlUsers = EOIR.User.loadUserFile(strCfgCode); 
	var nodes = xmlUsers.selectNodes("users/user");
	
	var arrUserList = [];
	
	for(var i = 0; i < nodes.length; i++)
	{
		var objUser = new EOIR.User(
			nodes[i].getAttribute("id"),
			nodes[i].getAttribute("name"),
			nodes[i].getAttribute("number"));
			
		objUser.getUserInfo();
		
		arrUserList.push(objUser);
	}

	return arrUserList;
}

EOIR.User.getUserXMLFromId = function(strId)
{
	if(strId == null) return null;

	if(EOIR.Utils.isWebBased() && !EOIR.Utils.isSCORMCompliant())
	{
		var node;
		try
		{
			node = EOIR.XML.load(EOIR.Utils.getAbsolutePath("/server_side/user.php?eval=user_get()&cfgcode=" + encodeURIComponent(EOIR.Utils.getPropertyDefault("cfgcode", "")) + "&id=" + encodeURIComponent(strId)));
		}
		catch(e) { node = null; }
		
		if(node != null)
		{
			node = node.documentElement;
		}
		return node;
	}
	else
	{
		return EOIR.User._getUserXMLFromIdDoc(strId, EOIR.User.loadUserFile());
	}
}

EOIR.User._getUserXMLFromIdDoc = function(strId, xmlUsers)
{
	if(xmlUsers == null)
	{
		return null;
	}
	
	return xmlUsers.selectSingleNode("users/user[translate(@id, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')='" + strId.toLowerCase() + "']");
}

EOIR.User.updateXML = function(strId, strXML)
{
	var strPostData = "eval=user_update()&cfgcode=" + encodeURIComponent(EOIR.Utils.getPropertyDefault("cfgcode", "")) + "&id=" + encodeURIComponent(strId) + "&xml=" + encodeURIComponent(strXML);
	try
	{
		var req = new XMLHttpRequest();
		req.open("POST", EOIR.Utils.getAbsolutePath("/server_side/user.php"), false);
		req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		req.send(strPostData);

		if(req.status == 200)
		{
			return req.responseText;
		}
	}
	catch(e)
	{
		// This is just in case the XMLHttpRequest object doesn't work.
		EOIR.XML.load(EOIR.Utils.getAbsolutePath("/server_side/user.php?" + strPostData));
	}
}

EOIR.User.getUserFromId = function(strId)
{
	try
	{
		var xmlUser = EOIR.User.getUserXMLFromId(strId);
		if(xmlUser != null)
		{
			var user = new EOIR.User(
					decodeAttribute(xmlUser.getAttribute("id")),
					decodeAttribute(xmlUser.getAttribute("name")),
					decodeAttribute(xmlUser.getAttribute("number")));

			user.getUserAttributesFromNode(xmlUser);
			return user;
		}
	}
	catch(e)
	{
	}
	
	return null;
}

EOIR.User.updateUserFile = function(strFile)
{
    var xml = EOIR.User.loadUserFileByName(strFile);
    
    var users = xml.selectNodes("users/user");
    for(var i = 0; i < users.length; i++)
    {
        if(users[i].getAttribute("vehicleset"))
        {
            //this is an oldschool user format. let's try to update it
            var vehicleset = users[i].getAttribute("vehicleset");
            var thermalpretestscore  = users[i].getAttribute("thermalpretestscore");
            var thermalpretestdate   = users[i].getAttribute("thermalpretestdate");
            var visiblepretestscore  = users[i].getAttribute("visiblepretestscore");
            var visiblepretestdate   = users[i].getAttribute("visiblepretestdate");
            var thermalposttestscore = users[i].getAttribute("thermalposttestscore");
            var thermalposttestdate  = users[i].getAttribute("thermalposttestdate");
            var visibleposttestscore = users[i].getAttribute("visibleposttestscore");
            var visibleposttestdate  = users[i].getAttribute("visibleposttestdate");
            
            users[i].removeAttribute("vehicleset");
            users[i].removeAttribute("thermalpretestscore");
            users[i].removeAttribute("thermalpretestdate");
            users[i].removeAttribute("visiblepretestscore");
            users[i].removeAttribute("visiblepretestdate");
            users[i].removeAttribute("thermalposttestscore");
            users[i].removeAttribute("thermalposttestdate");
            users[i].removeAttribute("visibleposttestscore");
            users[i].removeAttribute("visibleposttestdate");
            
            var elemTests = xml.createElement("tests");
            if(vehicleset && thermalpretestscore && thermalpretestdate)     
            {
                var elemTest = xml.createElement("test");
                elemTest.setAttribute("type", "pretest");
                elemTest.setAttribute("subtype", "thermal");
                elemTest.setAttribute("set", vehicleset);
                elemTest.setAttribute("score", thermalpretestscore);
                elemTest.setAttribute("date", thermalpretestdate);
                elemTests.appendChild(elemTest);
            }
            if(vehicleset && visiblepretestscore && visiblepretestdate)     
            {
                var elemTest = xml.createElement("test");
                elemTest.setAttribute("type", "pretest");
                elemTest.setAttribute("subtype", "visible");
                elemTest.setAttribute("set", vehicleset);
                elemTest.setAttribute("score", visiblepretestscore);
                elemTest.setAttribute("date", visiblepretestdate);
                elemTests.appendChild(elemTest);
            }
            if(vehicleset && thermalposttestscore && thermalposttestdate)    
            {
                var elemTest = xml.createElement("test");
                elemTest.setAttribute("type", "posttest");
                elemTest.setAttribute("subtype", "thermal");
                elemTest.setAttribute("set", vehicleset);
                elemTest.setAttribute("score", thermalposttestscore);
                elemTest.setAttribute("date", thermalposttestdate);
                elemTests.appendChild(elemTest);
            }
            if(vehicleset && visibleposttestscore && visibleposttestdate)    
            {
                var elemTest = xml.createElement("test");
                elemTest.setAttribute("type", "posttest");
                elemTest.setAttribute("subtype", "visible");
                elemTest.setAttribute("set", vehicleset);
                elemTest.setAttribute("score", visibleposttestscore);
                elemTest.setAttribute("date", visibleposttestdate);
                elemTests.appendChild(elemTest);
            }
            
            users[i].appendChild(elemTests);
        }
    }
    return xml;
}

EOIR.User.mergeUserFile = function(newXML, bAlwaysMerge, bAlwaysOverwrite, bAlwaysLeave)
{
    var curXML = EOIR.User.loadUserFile();
    //var newXML = EOIR.User.loadUserFileByName(strFile);
    
    var newUsers = newXML.selectNodes("users/user");
    for(var i = 0; i < newUsers.length; i++)
    {
        var curUser = curXML.selectSingleNode("users/user[@id = '" + newUsers[i].getAttribute("id") + "']");
        if(curUser)
        {
            //user already exists; merge or overwrite or leave?
            if(bAlwaysMerge)
            {
                //merge the old user with the new one
                throw "Not implemented - mergeUserFile's merge user functionality";
            }
            else if(bAlwaysOverwrite)
            {
                //easy one
                curXML.lastChild.removeChild(curUser);
                curXML.lastChild.appendChild(newUsers[i]);
            }
            else if(bAlwaysLeave)
            {
                ; //don't need to do anything here!           
            }
        }
        else
        {
            //new user; add it in!
            curXML.lastChild.appendChild(newUsers[i]);
        }
    }

    EOIR.Utils.writeXMLFile(curXML, EOIR.User.getUserInfoFile());
    

    //throw "Not implemented - mergeUserFile";
	/*var xmlMerge = new ActiveXObject("Msxml2.DOMDocument");
	xmlMerge.async = false;

	if(!xmlMerge.load(strFile))
	{
		showMessageBox("Could not load " + strFile + ". The file may be corrupt or you may not have permissions to access the file.", "Invalid File", MB_OK | MB_ICONEXCLAMATION);
		return false;
	}
	
	var xmlDst = loadUserFile();
	if(xmlDst == null)
	{
		showMessageBox("Could not load " + getUserInfoFile() + ". The file may be corrupt or you may not have permissions to access the file.", "Invalid File", MB_OK | MB_ICONEXCLAMATION);
		return false;
	}

	xmlDst.setProperty("SelectionLanguage", "XPath")
	
	var nodeUsersParentSrc = createXMLElementsIfNeeded(xmlMerge, "users");
	var nodeUsersParentDst = createXMLElementsIfNeeded(xmlDst, "users");
	
	var nodeUsersSrc = nodeUsersParentSrc.selectNodes("user");

	for(var i = 0; i < nodeUsersSrc.length; i++)
	{
		var nodeUserSrc = nodeUsersSrc[i];
		var strUserId = nodeUserSrc.getAttribute("id");

		var bOverwrite = true;		
//		alert("user[translate(@id, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')='" + strUserId.toLowerCase() + "'");
		var nodeUserDst = nodeUsersParentDst.selectSingleNode("user[translate(@id, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')='" + strUserId.toLowerCase() + "']");
		if(nodeUserDst == null)
		{
			nodeUserDst = createXMLElementWithAttribute(nodeUsersParentDst, "user", "id", strUserId);
		}
		else
		{
			if(showMessageBox("The user with id " + strUserId + " already exists. Would you like to overwrite the current user information with the one in the file being merged?", "Merge User Infomation", MB_YESNO | MB_ICONINFORMATION) == IDNO)
			{
				bOverwrite = false;
			}
		}
		
		if(bOverwrite)
		{
			var nodeUserAttribsSrc = nodeUserSrc.attributes;
			for(var j = 0; j < nodeUserAttribsSrc.length; j++)
			{
				nodeUserDst.setAttribute(nodeUserAttribsSrc[j].nodeName, nodeUserAttribsSrc[j].nodeValue);
			}
		}
	}	
	
	writeXMLFile(xmlDst, getUserInfoFile());*/
}

EOIR.User.createUser = function(strUserName, strNumber)
{
	var strID = escape(strUserName.toLowerCase() + strNumber.toLowerCase());
	var user = new EOIR.User(strID, strUserName, strNumber);

	// This may actually grab an existing user. Reset some of the info for that user (but don't reset the test info).
	user.clearProperty("vehicleset");
	user.clearProperty("customset");
	user.clearProperty("usecustomset");
	user.clearProperty("confsetnum");
	user.clearProperty("cstgtnum");
	user.clearProperty("maxsetnum");
	user.clearProperty("maxtgtnum");

	return user;
}

EOIR.User.createDemoUser = function()
{
	return new EOIR.User(null, null, null);
}

EOIR.User.isDemoUser = function(user)
{
	return user == null || user.ID == null;
}

EOIR.User.removeUser = function(user)
{
	if(EOIR.Utils.isWebBased() && !EOIR.Utils.isSCORMCompliant())
	{
		EOIR.XML.load(EOIR.Utils.getAbsolutePath("/server_side/user.php?eval=user_remove()&cfgcode=" + encodeURIComponent(EOIR.Utils.getPropertyDefault("cfgcode", "")) + "&id=" + encodeURIComponent(user.ID)));
	}
	else
	{
		var xmlUsers = EOIR.User.loadUserFile();
		var node = xmlUsers.selectSingleNode("users/user[@id = '" + user.ID + "']");
		if(node != null)
		{
			//remove node
			node.parentNode.removeChild(node);

			//save to file
			EOIR.Utils.writeXMLFile(xmlUsers, EOIR.User.getUserInfoFile());
		}
	}
}

EOIR.User.getUserInfoFileFromCode = function(strCode)
{
	if(strCode == null || strCode.length == 0 || strCode.toLowerCase() == "default")
	{
		return EOIR.Utils.getAbsolutePath("/config/users.xml");
	}
	else
	{
		return EOIR.Utils.getAbsolutePath("/config/users-" + strCode.toLowerCase() + ".xml");
	}
}

EOIR.User.getUserInfoFile = function(strCode)
{
	try
	{
		if(!EOIR.Utils.isInROCBrowser() && !EOIR.Utils.isInROCBrowserGecko())
		{
			if(strCode == null)
			{
				strCode = EOIR.Utils.getProperty("cfgcode");
			}
			return EOIR.User.getUserInfoFileFromCode(strCode);
		}
		else
		{
			var strUserInfoFile = EOIR.Utils.getPropertySetEvalDefault("UserInfoFile", "EOIR.External.get().UserInfoFilename");
			if(strUserInfoFile != null)
			{
				return strUserInfoFile;
			}
			else
			{
			    try
			    {
			        var strUserInfoDir = EOIR.External.getUserHomeDir();
			        strUserInfoDir = EOIR.Utils.appendSep(strUserInfoDir) + EOIR.External.getProduct();
			        if(strUserInfoDir.indexOf("file:///") != -1)
			        {
			            strUserInfoDir = strUserInfoDir.substr(8);
			        }
			        strUserInfoDir = EOIR.Utils.appendSep(strUserInfoDir);
			        EOIR.External.makeSureDirExists(strUserInfoDir);
			        
			        strUserInfoDir = strUserInfoDir.replace(/\\/g, "/");
			        strUserInfoFile = EOIR.Utils.buildPath("file:///" + strUserInfoDir, "users.xml");
			    }
			    catch(e){}
			    
			    if(strUserInfoFile != null)
			    {
			        EOIR.Utils.setProperty("UserInfoFile", strUserInfoFile);
			        return strUserInfoFile;
			    }
			}
		}
	}
	catch(e)
	{
	}

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

EOIR.User.get = function()
{
	var user = EOIR.Utils.getProperty("User");

	if(user != null)
	{
		// Can't just get the user property.
		// JavaScript objects (at least their functions) don't work across frames, so
		// we need to create a new user and clone its functions onto the cached object.
		var userTemp = new EOIR.User();
		for(var i in userTemp)
		{
			if(typeof (userTemp[i]) == "function")
			{
				user[i] = userTemp[i];
			}
		}
	}
	else
	{
		user = EOIR.User.createDemoUser();
		EOIR.User.set(user);
	}

	return user;
}

EOIR.User.set = function(user)
{
	EOIR.Utils.setProperty("User", user);
}

EOIR.User.getSafeUser = function()
{
	var user = EOIR.User.get();
	if(user == null)
	{
	    user = EOIR.User.createDemoUser();
	}
	return user;
}

EOIR.User.getCurrentUserProperty = function(strPropName, defaultVal)
{
	var user = EOIR.User.get();
	if(user != null)
	{
		return user.getProperty(strPropName, defaultVal);
	}

	return defaultVal;
}

EOIR.User.setCurrentUserProperty = function(strPropName, val)
{
	var user = EOIR.User.get();
	if(user != null)
	{
		user.setProperty(strPropName, val);
	}
}

EOIR.User.clearCurrentUserProperty = function(strPropName)
{
	var user = EOIR.User.get();
	if(user != null)
	{
		user.clearProperty(strPropName);
	}
}

EOIR.User.getConfusionSets = function()
{
	if(EOIR.User.getCurrentUserProperty("usecustomset", false))
	{
		var strConfSets = EOIR.User.getCurrentUserProperty("customset", null);
		if(strConfSets != null)
		{
			var arrConfSets = strConfSets.split(":");
			for(var i = 0; i < arrConfSets.length; i++)
			{
				arrConfSets[i] = arrConfSets[i].split(",");
			}

			return arrConfSets;
		}
		return null;
	}

	return null;
}
