
//File: common.js
//Author: Richard Ansara
//Use:  Common functions needed for the fusion library

//Returns the full path to the fusion library root directory
//Pass boolean true for localhost
function getFusionHost(useDev)
{    
    var fusionHostString = "";
    
    if(useDev)
        fusionHostString = "http://localhost/clients/controls/fusion/"
    else
        fusionHostString = window.location.protocol + "//" + window.location.hostname + "/clients/controls/fusion/";
    
    return fusionHostString;
}

//Returns an XMLHttpRequest object for the appropriate browser
function getAjaxObject()
{
    var request = false;
    
    if(window.ActiveXObject)
    {   
        try
        {
            request = new ActiveXObject("Msxml2.XMLHTTP");            
        }
        catch(e)
        {
            request = new ActiveXObject("Microsoft.XMLHTTP");            
        }
    }    
    else if(window.XMLHttpRequest)
    {
        request = new XMLHttpRequest();        
    }
    
    return request;
}

//Removes html and body tags from the response
function filterResponse(response)
{
     var trailerString = "<html><body></body></html>";
	 var trailerPosition = response.indexOf(trailerString);		
	 var cleanResponse = response.substring(0, trailerPosition);
	 return cleanResponse;
}

//Replaces a value in a string with the given replacement
function stringReplace(strValue, strToReplace, strReplacement)
{
    var newString = "";
    
    for(var x=0; x<strValue.length; x++)
    {
        var currentChar = strValue.substr(x, 1);
        
        if(currentChar == strToReplace)
            newString = newString + strReplacement;
        else
            newString = newString + currentChar;
    }
    
    return newString;
}

//File: UserInfo.js
//Author: Richard Ansara
//Use:  UserInfo object to view name, email, subscriptions, attributes, entitlements

//UserInfo class constructor
function UserInfo(strProduct)
{
    this.product = strProduct

    //Items set after WSK call
	this.isValid = false;
	this.properties = null;
	this.subscriptions = null;
	this.entitlements = null;
	this.attributes = null;
	this.menus = null;
}

//Execute method populates class
UserInfo.prototype.execute = function()
{
	var http = new HttpRequest();
	http.setTarget(getFusionHost() + "GetUserInfo.aspx");
	http.setForm(new URLBuilder("product", this.product));
	http.requestHeaders.Accept = 'text/plain';
	this._setUserProperties(http.post())
}

//Method called using asynchronous AJAX call
UserInfo.prototype._setUserProperties = function(userResponse)
{
    userResponse = filterResponse(userResponse);

	//If we got a non-null response
	if(userResponse != "")
	{
		//Eval the JSON object into a JS object
		var userInfo = eval("(" + userResponse + ")");

	    //Assign this objects values to those of the returned JS object
	    if(userInfo.properties)
	        this.properties = userInfo.properties;
	    if(userInfo.subscriptions)
		    this.subscriptions = userInfo.subscriptions;
		if(userInfo.entitlements)
		    this.entitlements = userInfo.entitlements;
		if(userInfo.attributes)
		    this.attributes = userInfo.attributes;
		if(userInfo.menus)
			this.menus = userInfo.menus;

		//Set status flag to true
		this.isValid = true;
	}
	else
	{
		//User response was null, set status flag to false
		this.isValid = false;
	}
}

//View the subscriptions for this user
UserInfo.prototype.viewSubscriptions = function()
{
    var subscriptionString = "";

    if(this.subscriptions.length > 0)
    {
        subscriptionString = "Available subscriptions: \n\n";

        for(x=0; x<this.subscriptions.length; x++)
        {
            subscriptionString += this.subscriptions[x].subscriptionName + " (id: " + this.subscriptions[x].subscriptionId + ")\n";
        }
    }
    else
        subscriptionString = "No available subscriptions";

    alert(subscriptionString);
}

//Check if this user is subscribed to a certain subscription
UserInfo.prototype.isUserSubscribed = function(subscriptionId)
{
    var found = false;
    if(this.subscriptions.length > 0)
    {
        for(x=0; x<this.subscriptions.length; x++)
        {
            if(this.subscriptions[x].subscriptionId == subscriptionId)
            {
                found = true;
                break;
            }
        }
    }
    return found;
}

//Get a subscription name for a subscription ID
UserInfo.prototype.getSubscriptionName = function(subscriptionId)
{
    var subscriptionName = "";
    if(this.subscriptions.length > 0)
    {
        for(x=0; x<this.subscriptions.length; x++)
        {
            if(this.subscriptions[x].subscriptionId == subscriptionId)
            {
                subscriptionName = this.subscriptions[x].subscriptionName;
                break;
            }
        }
    }
    return subscriptionName;
}

//Display the users entitlements
UserInfo.prototype.viewEntitlements = function(entitlementName)
{
    var entitlementString = "";

    if(this.entitlements.length > 0)
    {
        entitlementString = "Entitlement Detail: \n\n";

        for(x=0; x<this.entitlements.length; x++)
        {
            entitlementString += this.entitlements[x].entitlementName + " (access: " + this.entitlements[x].entitlementAccess + ")\n";
        }
    }
    else
        entitlementString = "No available entitlements";

    alert(entitlementString);
}

//Check user's access to an entitlement
UserInfo.prototype.isUserEntitled = function(entitlementName)
{
    var entitlementAccess = false;

    if(this.entitlements.length > 0)
    {
        for(x=0; x<this.entitlements.length; x++)
        {
            if(this.entitlements[x].entitlementName == entitlementName)
            {
               if(this.entitlements[x].entitlementAccess == "True")
                    entitlementAccess = true;
               else
                    entitlementAccess = false;
               break;
            }
        }
    }
    return entitlementAccess;
}

//Check the value of a given attribute
UserInfo.prototype.GetAttributeValue = function(attributeName)
{
    var attributeValue = "";

    if(this.attributes.length > 0)
    {
        for(x=0; x<this.attributes.length; x++)
        {
            if(this.attributes[x].attributeName == attributeName)
            {
                attributeValue = this.attributes[x].attributeValue;
                break;
            }
        }
    }
    return attributeValue;
}

//Display the users attributes
UserInfo.prototype.viewAttributes = function()
{
    var attributeString = "";

    if(this.attributes.length > 0)
    {
        attributeString = "Attribute Detail: \n\n";

        for(x=0; x<this.attributes.length; x++)
        {
            attributeString += this.attributes[x].attributeName + " (value: " + this.attributes[x].attributeValue + ")\n";
        }
    }
    else
        attributeString = "No available attributes";

    alert(attributeString);
}

// Check if a user has a menu.
UserInfo.prototype.hasMenu = function(menu)
{
	var found = false;

	for (var x = 0; !found && x < this.menus.length; ++x)
	{
		found = (menu == this.menus[x]);
	}

	return found;
}

//Display the user's menus
UserInfo.prototype.viewMenus = function()
{
    var menuString = "";

    if(this.menus.length > 0)
    {
        menuString = "Menus: \n\n";

        for(x=0; x<this.menus.length; x++)
        {
            menuString += this.menus[x] + "\n";
        }
    }
    else
        MenuString = "No available menus";

    alert(menuString);
}



//SegmentBuddy class constructor
function SegmentBuddy(source)
{    
    this.segmentList = null;
    this.csi = null;
    this.loadedSources = new Array();
    this.loadedSegments = new Array();
    
    if(source != undefined && source != "")        
        this.loadSegments(source);    
}

SegmentBuddy.prototype.loadSegments = function(source)
{   
    if(source == "" || source == undefined)
    {
        alert("No source provided.");
    }    
    else
    {   
        this.csi = stringReplace(source, " ", "");
    }        
    
    //Check if the source was already loaded
    if(this._isLoaded(this.csi))
        this._makeCurrent(this.csi) //Make already loaded source current
    else //Get segments from wsk
        this._getSegments(this.csi);  
}

//public
SegmentBuddy.prototype.getSegments = function()
{
    return this.segmentList;
}

//public
SegmentBuddy.prototype.fillSegments = function(objSegmentList)
{
    objSegmentList.options.length = this.segmentList.length + 1
    objSegmentList.options[0].value = "";
    objSegmentList.options[0].text = "Select a Segment";
    
    for(x=1; x<=this.segmentList.length; x++)
    {
        objSegmentList.options[x].value = this.segmentList[x-1];
        objSegmentList.options[x].text = this.segmentList[x-1];
    }
    
    objSegmentList.selectedIndex = 0;
}

//PRIVATE METHOD AREA
//Checks to see if the source being loaded was already loaded to avoid WSK call
SegmentBuddy.prototype._isLoaded = function(source)
{
    var loaded = false
    for(x=0; x<this.loadedSources.length; x++)
    {
        if(this.loadedSources[x] == source)
        {
            loaded = true;
            break;
        }        
    }
    return loaded;
}

//private
//Makes an already loaded source the current source by setting segmentList
SegmentBuddy.prototype._makeCurrent = function(source)
{
    for(x=0; x<this.loadedSources.length; x++)
    {
        if(this.loadedSources[x] == source)
        {
            this.segmentList = this.loadedSegments[x];
            break;
        }        
    }   
}

//private
//Creates a new array and adds it to previously loaded sources array
SegmentBuddy.prototype._storeArray = function(newSegmentList)
{   
   this.loadedSources[this.loadedSources.length] = this.csi;
   this.loadedSegments[this.loadedSegments.length] = newSegmentList;
}

//private
SegmentBuddy.prototype._getSegments = function(csi)
{
    var http = new HttpRequest();    
	http.setTarget(getFusionHost() + "GetSegments.aspx");
	http.setForm(new URLBuilder("csi", csi));
	http.requestHeaders.Accept = 'text/plain';
	this._setSegmentArray(http.post());
}

//private
SegmentBuddy.prototype._setSegmentArray = function(segmentResponse)
{
    segmentResponse = filterResponse(segmentResponse);
    
    if(segmentResponse != "")
    {   
        this.segmentList = segmentResponse.split(',');
        this._storeArray(this.segmentList);        
    }
}

function SourceConverter()
{
    if(isDev())
        alert("SourceConverter is static.  Do not instantiate.");
}

SourceConverter.convert = function(strLibFile)
{       
        if(strLibFile != "" && typeof strLibFile != "undefined")
        {
            if(strLibFile.indexOf(";") != 0)
            {
                var sourceValueArray = strLibFile.split(';');
                
                if (sourceValueArray.length == 2 && sourceValueArray[1] != "")
                {
                    var http = new HttpRequest();
	                http.setTarget(getFusionHost() + "ConvertSources.aspx");
	                http.setForm(new URLBuilder("lib", sourceValueArray[0], "file", sourceValueArray[1]));
	                http.requestHeaders.Accept = 'text/plain';
	                var csi = this._cleanSourceValue(http.post());	                
	                
	                if(csi == "invalid")
	                    csi = "0";
	                    	                
	                return csi;
                }
                else
                {
                    alert("Source (" + strLibFile + ") is not in correct lib;file format.");
                    return "invalid";
                }            
	        }
	        else
	        {
	            alert("Source (" + strLibFile + ") is not in correct lib;file format.");
	            return "invalid";
	        }
        }
        else
        {
            alert("Source lib;file cannot be null.");
            return "invalid";
        }         
}

//Used to trim tags in the document	
SourceConverter._cleanSourceValue = function(sourceResponse)
{     
	sourceResponse = filterResponse(sourceResponse);
	return sourceResponse;
}



//SearchInfo class constructor
function SearchInfo(strSearch, strSource, strSearchName, strProduct)
{
	//Items to use with WSK
	this.search = strSearch;
	this.source = strSource;
	this.searchName = strSearchName;
	this.product = strProduct;
		
	//Items set after WSK call
	this.docsFound = 0;
	this.resultHandle = null;
}

//Execute method populates class
SearchInfo.prototype.execute = function()
{
	var http = new HttpRequest();	
	http.setTarget(getFusionHost() + "GetSearchInfo.aspx");
	http.setForm(new URLBuilder("search", this.search, "source", this.source, "searchName", this.searchName, "product", this.product));
	http.requestHeaders.Accept = 'text/plain';	
	this._setSearchInfoProperties(http.post());
}

//Method called using asynchronous AJAX call
SearchInfo.prototype._setSearchInfoProperties = function(searchResponse)
{	
    searchResponse = filterResponse(searchResponse);
    var resultArray = searchResponse.split("/");
    this.docsFound = resultArray[0];
    this.resultHandle = resultArray[1];
    this.searchName = resultArray[2];	
}



//SourceInfo class constructor
function SourceInfo(strCsiList, strProduct)
{
	if(strCsiList == "")	
	    alert("CSI value cannot be blank.");	
	else
	    strCsiList = stringReplace(strCsiList, " ", "");
	    
	//Items to use with WSK
	this.csiList = strCsiList;
	this.product = strProduct;
	
	//Items set after WSK call
	this.sourceList = null;
}

//Execute method populates class
SourceInfo.prototype.execute = function()
{
	//For legacy (lexis) users (calls LegacyGetSourceList)
	var target = "GetSourceInfo.aspx";
	
	//Otherwise, use the Rosetta Source Info (calls GetSourceDetails)
	if(this.product != "lexis")
	{
	    target = "GetRosettaSourceInfo.aspx";
	    
	    //Rosetta calls GetSourceDetails which can only take 1 csi at a time
	    if(this.csiList.indexOf(',') != -1)
	        alert("Since this is a Rosetta call, only your first CSI will be used by SourceInfo.");
	}	    
	
	var http = new HttpRequest();	
	http.setTarget(getFusionHost() + target);
	http.setForm(new URLBuilder("product", this.product, "srcList", this.csiList));
	http.requestHeaders.Accept = 'text/plain';
	this._setSourceProperties(http.post())
}

//Method called using asynchronous AJAX call
SourceInfo.prototype._setSourceProperties = function(sourceResponse)
{	
    sourceResponse = filterResponse(sourceResponse);
	
	//If we got a non-null response
	if(sourceResponse != "")
	{		
		//Eval the JSON object into a JS object
		var sourceInfo = eval("(" + sourceResponse + ")");
	    
	    //Assign this object's values to those of the returned JS object
	    if(sourceInfo.sourceList)	    
	        this.sourceList = sourceInfo.sourceList;	    
	}
}

//Check if this user is subscribed to a certain subscription
SourceInfo.prototype.isTransactional = function(csi)
{
    var transactional = false;
    
    if(this.sourceList.length > 0)
    {
        for(x=0; x<this.sourceList.length; x++)
        {
            if(this.sourceList[x].csi == csi)
            {
                if(this.sourceList[x].isTransactional == "True")
                    transactional = true;                   
                
                break;
            }
        }
    }    
    return transactional;
}

//SourceNames class constructor.  Used to retrieve source names when user information is not available.
function SourceNames(strCsiList)
{
	if(strCsiList == "")
	    alert("CSI value cannot be blank.");	
	else
	    strCsiList = stringReplace(strCsiList, " ", "");
	    
	//Items to use with WSK
	this.csiList = strCsiList;
	
	//Items set after WSK call
	this.sourceList = null;
}

//Execute method populates class
SourceNames.prototype.execute = function()
{
	var target = "GetSourceNames.aspx";
	var http = new HttpRequest();	
	http.setTarget(getFusionHost() + target);
	http.setForm(new URLBuilder("srcList", this.csiList));
	http.requestHeaders.Accept = 'text/plain';
	this._setSourceProperties(http.post())
}

//Method called using a synchronous AJAX call
SourceNames.prototype._setSourceProperties = function(sourceResponse)
{	
	//If we got a non-null response
	if(sourceResponse != "")
	{		
		//Eval the JSON object into a JS object
		var sourceNames = eval("(" + sourceResponse + ")");
	    
	    //Assign this object's values to those of the returned JS object
	    if(sourceNames.sourceList)	    
	        this.sourceList = sourceNames.sourceList;	    
	}
}

//SearchInfo class constructor
function Search(strSearch, strSource)
{
	//Items to use with WSK
	this.search = strSearch;
	this.source = strSource;    
   
	//Items set after WSK call
	this.docsFound = 0;	
	this.searchResults = null;
}

//Execute method populates class
Search.prototype.execute = function()
{
	var http = new HttpRequest();	
	http.setTarget(getFusionHost() + "GetSearchResults.aspx");
	http.setForm(new URLBuilder("search", this.search, "source", this.source));
	http.requestHeaders.Accept = 'text/plain';	
	this._setSearchProperties(http.post());
}

//Method called using asynchronous AJAX call
Search.prototype._setSearchProperties = function(searchResponse)
{	
    searchResponse = filterResponse(searchResponse);
      
    if(searchResponse != "")
    {            
        var responseArray = searchResponse.split('/***/');        
        
        if(responseArray[1] > 0)
        {
            var objSearchResponse = eval("(" + responseArray[0] + ")");
            this.searchResults = objSearchResponse.documentList;            
            this.docsFound = this.searchResults.length;
        }
        else
        {
            this.docsFound = responseArray[1];
        }
    }
}



//SingleDoc class constructor
function SingleDoc(strSearch, strSource, strProduct)
{
	//Items to use with WSK
	this.search = strSearch;
	this.source = strSource;	
	this.product = strProduct;
		
	//Items set after WSK call
	this.returnCode = 0;
	this.doc = null;
}

//Execute method populates class
SingleDoc.prototype.execute = function()
{   
	var http = new HttpRequest();	
	http.setTarget(getFusionHost() + "GetSingleDoc.aspx");
	http.setForm(new URLBuilder("search", this.search, "source", this.source, "product", this.product));
	http.requestHeaders.Accept = 'text/plain';	
	this._setSingleDocProperties(http.post());
}

//Method called using asynchronous AJAX call
SingleDoc.prototype._setSingleDocProperties = function(searchResponse)
{	
    searchResponse = filterResponse(searchResponse);
    var resultArray = searchResponse.split("/***/");
    this.returnCode = resultArray[1];
    this.doc = resultArray[0];	
}

function HttpRequest(returnType)
{
	// Are we returning XML or Text
	if (returnType) {
		this._returnType = returnType
	}
	else
	{
		this._returnType = HttpRequest.RESPONSE_TEXT
	}

	this.xmlhttp = new XMLHttpRequest();

	this.requestHeaders     = new Object();

	// Target defaults to self
	this._target = document.URL

	this._form

}

/**
 * Constant for returning XML
 */
HttpRequest.RESPONSE_XML = "responseXML"

/**
 * Constant for returning Text
 */
HttpRequest.RESPONSE_TEXT = "responseText"


HttpRequest.prototype.getTarget = function()
{
	return this._target
}

HttpRequest.prototype.setTarget = function(target)
{
	this._target = target
}

HttpRequest.prototype.getForm = function()
{
	return this._form
}

HttpRequest.prototype.setForm = function(form)
{
	if (typeof(form) == "object")
	{
		this._form = form.toString()
	}
	else
	{
		this._form = form
	}
}

HttpRequest.prototype._getURI = function()
{
	if (this._form) {
		return this._target + "?" + this._form
	}
	return this._target
}

HttpRequest.prototype.get = function(closure)
{
	if (closure)
	{
		this.asynchronousGet(closure)
	}
	return this.synchronousGet()
}

HttpRequest.prototype.post = function(closure)
{
	if (closure)
	{
		this.asynchronousPost(closure)
	}
	return this.synchronousPost()
}

HttpRequest.prototype.asynchronousGet = function(closure)
{
	// This, as in the this Object, no longer refers to this in closures,
	// so we need to copy it.
	// A good article on this is
	// http://w3future.com/html/stories/callbacks.xml
	var me = this

	// For asynchronous calls you can't use on
	var http = new XMLHttpRequest();
	http.open("GET", this._getURI(), true)

	http.onreadystatechange = function()
    {
        if(http.readyState == 4)
        {
            http.onreadystatechange = function(){}

            if (closure != null)
            {
				closure(http[me._returnType])
			}
        }
    };
	http.send(null)
}

HttpRequest.prototype.asynchronousPost = function(closure)
{
	var me = this
	var http = new XMLHttpRequest();

	http.open("POST", this.getTarget(), true);
	http.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8")

	http.onreadystatechange = function()
    {
        if(http.readyState == 4)
        {
            http.onreadystatechange = function(){}

            closure(http[me._returnType])
        }
    };
	http.send(this.getForm())
}


HttpRequest.prototype.synchronousGet = function()
{
	var ret = ""

	this.xmlhttp.open("GET", this._getURI(), false)

	for(var header in this.requestHeaders)
	{
        this.xmlhttp.setRequestHeader(header, this.requestHeaders[header])
	}

	this.xmlhttp.send(null)
	if (this.xmlhttp.status == 200)
	{
		ret = this.xmlhttp.responseText
	}
	return ret
}

HttpRequest.prototype.synchronousPost = function(target, content)
{
	var ret = ""

	this.xmlhttp.open("POST", this.getTarget(), false);

	// Needed for form posting
	this.xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8")
	for(var header in this.requestHeaders)
	{
        this.xmlhttp.setRequestHeader(header, this.requestHeaders[header])
	}

	this.xmlhttp.send(this.getForm())
	if (this.xmlhttp.status == 200)
	{
		ret = this.xmlhttp.responseText
	}
	return ret
}

////////////////////////////////////////////////////////////////////////////////
// XMLHttpRequest

/**
 * Cross-browser XMLHttpRequest instantiation. Posted by Gyoung-Yoon Noh
 * on the Ruby on Rails mailing list.
 *
 * Usage:
 *
 *        xmlhttp = new XMLHttpRequest()
 *
 * @author Gyoung-Yoon Noh
 * @link   http://hieraki.goodlad.ca/read/chapter/8#page16
 */


if ((typeof XMLHttpRequest == 'undefined') ||
	 (typeof XMLHttpRequest == null) ||
	  (typeof XMLHttpRequest == undefined))
{
	XMLHttpRequest = function ()
	{
		var msxmls = ['MSXML3', 'MSXML2', 'Microsoft']
		for (var i=0; i < msxmls.length; i++)
		{
			try
			{
				return new ActiveXObject(msxmls[i]+'.XMLHTTP')
			}
			catch (e) { }
		}
		//throw new Error("No XML component installed!")
	}
}








// XMLHttpRequest
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// URLBuilder

/**
 * Class to facilitate GET and POST query strings.
 *
 * Vars can be passed in through the constructor:
 *
 *    var u = new URLBuilder("word", "ping", "name", "pang")
 *
 * u.toString() returns "word=ping&name=pang"
 */
function URLBuilder()
{
	this._vars = new Object()

	if (arguments.length > 0)
	{
		for (var x = 0; x < arguments.length; x = x + 2)
		{
			if (arguments[x + 1] == undefined)
			{
				arguments[x + 1] = ""
			}
			this.addVar(arguments[x], arguments[x + 1])
		}
	}
}

URLBuilder.prototype.addVar = function(key, val)
{
	this._vars[encodeURIComponent(key)] = encodeURIComponent(val)
}

URLBuilder.prototype.toString = function()
{
	var delim = '';
	var url = '';
	for (key in this._vars)
	{
		url += delim + key + '=' + this._vars[key];
			delim = '&'
	}
	return url
}