/**
 * Store cookie requests for each browser host
 * @type cookieMonsterBys1tony.cookieRequest
 */
cookieMonsterBys1tony.cookieRequest = 
{
    _uriList: new Object(),
    _browserList: new Array(),
    //_testList: new Array(),
    _cm: cookieMonsterBys1tony,

    init: function()
    {
		// Do nothing for now   
    },

	/**
	 * Check if the host is already contained in this list
	 * @param {} aList
	 * @param {} elt
	 * @return Integer
	 */
    _requestHostIndexOf: function(aList, elt /*, checkDomain, from*/)
	{
		var len = aList.length >>> 0;
		var checkDomain = arguments[2] ? Boolean(arguments[2]) : false;
		var from = arguments[3] ? Number(arguments[3]) || 0 : 0;		

		from = (from < 0)
			? Math.ceil(from)
			: Math.floor(from);
			
		if (from < 0)
			from += len;

		if (!checkDomain)
		{
			for (; from < len; from++)
			{
	  			//if (from in aList &&
	      		//	aList[from].host === elt.host)
			    if (from in aList && aList[from].uri.equalsExceptRef(elt.uri))
			    {
			        return from;
			    }
			}
		}
		else
		{
			for (; from < len; from++)
			{		
			    //if (from in aList &&
			    //	this._cm.cookieInfo.getSecondLevelHost(aList[from].host) === elt.host)
			    if (from in aList && this._cm.cookieInfo.getSecondLevelURI(aList[from].uri).equalsExceptRef(elt.uri))
			    {
			        return from;
			    }
			}
		}
		
		return -1;		
	},

	/**
	 * Check if the property is already contained in this list
	 * @param {} aList
	 * @param {} aProperty
	 * @param {} aValue
	 * @return Integer
	 */
    _requestPropertyIndexOf: function(aList, aProperty, aValue /*, from*/)
	{
		var len = aList.length >>> 0;
		var from = arguments[3] ? Number(arguments[3]) || 0 : 0;

		from = (from < 0)
			? Math.ceil(from)
			: Math.floor(from);
			
		if (from < 0)
			from += len;

		for (; from < len; from++)
		{
  			if (from in aList &&
      			aList[from][aProperty] === aValue)
    		return from;    		
		}
	
		return -1;		
	},
	
	containsHost: function(aHost)
	{
		return this._uriList.hasOwnProperty(aHost);	
	},
	
	hasMadeCookieRequest: function(aHost)
	{
		var retValue = false;
		
		if (this.containsHost(aHost))
		{
			retValue = this._uriList[aHost].hasMadeCookieRequest;
		}		

		return retValue;		
	},
	
	/**
	 * Add cookie request to browser list
	 * @param {String} aCookieHost
	 * @param {Browser} aBrowser
	 * @param {Boolean} aIsDomain
	 */
	addCookieRequest: function(aCookieHost, aBrowser, aIsDomain)
	{
	    //console.log("Got to addCookieRequest");

		if (aBrowser)
		{
			// Check if this browser is already contained in the list
			var browserIndex = this._requestPropertyIndexOf(this._browserList, 'browser', aBrowser);
			var cookieHostInfo = { host: aCookieHost.prePath, isDomain: aIsDomain };

			//console.log("Got to addCookieRequest with an aCookieHost: " + aCookieHost.asciiHost);
			//console.log("Got to addCookieRequest with aBrowser: " + aBrowser.lastURI.asciiHost);

	    	if (browserIndex > -1)
	    	{
	    		this._browserList[browserIndex].cookieRequestList.push(cookieHostInfo);
	    		//this._testList.push(cookieHostInfo);
	    		//console.log("Got to addCookieRequest for existing browser adding cookieHostInfo: " + cookieHostInfo.host);
	    	}
	    	else
	    	{
	    	    this._browserList.push({ browser: aBrowser, cookieRequestList: new Array(cookieHostInfo) });
	    	    //this._testList.push(cookieHostInfo);
	    	    //console.log("Got to addCookieRequest for new browser adding cookieHostInfo: " + cookieHostInfo.host);
    		}
    		
    		//alert("Add Cookie Request Browser:  " + aBrowser.currentURI.asciiHost + " cookieURI:  " + aCookieURI);
		}
	},

	/**
	 * Process Cookie Requests for aBrowser
	 * @param {Browser} aBrowser
	 */
	processCookieRequests: function(aBrowser)
	{
		// Check if this browser is contained in the list
		var browserIndex = this._requestPropertyIndexOf(this._browserList, 'browser', aBrowser);

    	if (browserIndex > -1)
    	{
    		var browserHost = aBrowser.currentURI.asciiHost;
    		    		
			// Process each cookie URI in array for aBrowser
			for (var i = 0, cookieHostInfo; cookieHostInfo = this._browserList[browserIndex].cookieRequestList[i]; i++)
			{
				this._processCookieRequest(cookieHostInfo.host, browserHost, cookieHostInfo.isDomain);
			}
			
//    		alert("Loading Cookies for Browser Host: " + browserHost +
//    			  "\nNumber of 3rd Party Cookies: " + this._uriList[browserHost].cookieRequestList.length +
//    			  "\nHost attempted to leave Cookie: " + this._uriList[browserHost].hasMadeCookieRequest);
		}
	},
	
	_processCookieRequest: function(aCookieURI, aLoadHost /*, aIsDomain  */)
	{				
		if (!(aCookieURI instanceof Components.interfaces.nsIURI))
		{
			aCookieURI = this._cm.utils.createURIFromHostName(aCookieURI, true);
		}

		var aIsDomain = arguments[2] ? Boolean(arguments[2]) : false;
		var secondLevelCookieHost = this._cm.cookieInfo.getSecondLevelHost(aCookieURI.asciiHost);
 		var secondLevelLoadHost;
 		
		// First of all, check to see if aLoadHost is null     
    	if (aLoadHost != null)
    	{
      		secondLevelLoadHost = this._cm.cookieInfo.getSecondLevelHost(aLoadHost);
      		
			// Check if this host is already contained in the list
			if (!this._uriList.hasOwnProperty(aLoadHost))
			{
				this._uriList[aLoadHost] = new Object();
				this._uriList[aLoadHost].cookieRequestList = new Array();
	        	this._uriList[aLoadHost].hasMadeCookieRequest = false;		
			}

	    	//alert("Process secondLevelCookieHost:  " + secondLevelCookieHost + "  secondLevelLoadHost:  " + secondLevelLoadHost);
					    	
	    	// Filter out cookies from the load host
	        if (secondLevelCookieHost != secondLevelLoadHost)
	        {
	        	// If this is a domain cookie request, then convert
	        	// aCookieURI to a domain
	        	if (aIsDomain)
	        	{
		    		aCookieURI = this._cm.cookieInfo.getSecondLevelURI(aCookieURI);	        		
	        	}
	        	
				// Check if URI already has a non-default cookie access
				// Use CM_URL_STANDARD_LEVEL in order to reflect the result
				// of aCookieURI
		        var accessLevel = this._cm.cookieInfo.checkPermissionArray(aCookieURI, CM_PERMISSION_TYPE_COOKIE);
		        var accessValue = this._cm.cookieInfo.getPermissionValue(accessLevel[CM_URL_STANDARD_LEVEL]);
				var cookieInfo = {uri: aCookieURI, accessValue: accessValue};
				
		        // Check if this URI is already contained in the list for the host and
				// if so, check to see if the accessValue has changed
		    	// Also check for the situation where the TOP LEVEL URL may already be
		    	// in the list and a Domain cookie being added
				var hostIndex = this._requestHostIndexOf(this._uriList[aLoadHost].cookieRequestList, cookieInfo);
		    	
		    	//alert("hostIndex:  " + hostIndex + "  _uriList:  " + this._uriList.toSource());
		    	//alert("Process secondLevelCookieHost:  " + secondLevelCookieHost + "  secondLevelLoadHost:  " + secondLevelLoadHost);
		    	
		    	if (hostIndex > -1)
		    	{
		    		if (this._uriList[aLoadHost].cookieRequestList[hostIndex].accessValue != accessValue)
		    		{
		    			this._uriList[aLoadHost].cookieRequestList[hostIndex].accessValue = accessValue;
		    		}
		    	}
		    	else
		    	{
		        	this._uriList[aLoadHost].cookieRequestList.push(cookieInfo);	    		
		    	}	    	
	        }
	        else
	        {
	        	this._uriList[aLoadHost].hasMadeCookieRequest = true;
	        }
		}
	},
	
	_refreshCookieRequest: function(aLoadHost)
	{
		if (this.containsHost(aLoadHost))
		{
		    this._uriList[aLoadHost].cookieRequestList.forEach(
			    function(tempCookieItem, index)
			    {
				    this._processCookieRequest(tempCookieItem.uri, aLoadHost);
		    	}, this
		    );		
		}
	},
	
	/**
	 * Update the cookie info for aCookieHostURI
	 * @param {nsIURI [could also accept String]} aCookieHostURI
	 * @param {String} aHost
	 */
	updateCookieRequest: function(aCookieHostURI, aHost)
	{
	    this._processCookieRequest(aCookieHostURI, aHost);
	},
	
	/**
	 * Retrieve cookie request list for aLoadHost
	 * @param {String} aLoadHost
	 * @return {cookieInfo[]} cookieInfo {uri: accessValue:} objects
	 */
	getRequestList: function(aLoadHost)
	{
		var retValue = null;
		
		if (this.containsHost(aLoadHost))
		{
			this._refreshCookieRequest(aLoadHost);
			retValue = this._uriList[aLoadHost].cookieRequestList;	
		}

		return (retValue != undefined) ? retValue : null;
	},
	
	/**
	 * Clear cookie requests from aBrowser
	 * @param {Browser} aBrowser
	 */
	clearBrowser: function(aBrowser)
	{
		// Check if this browser is contained in the list
		var browserIndex = this._requestPropertyIndexOf(this._browserList, 'browser', aBrowser);

    	if (browserIndex > -1)
    	{
			this._browserList[browserIndex].cookieRequestList = new Array();
		}
	},
	
	/**
	 * Remove aBrowser from browser list
	 * @param {Browser} aBrowser
	 */
	removeBrowser: function(aBrowser)
	{
		// Check if this browser is contained in the list
		var browserIndex = this._requestPropertyIndexOf(this._browserList, 'browser', aBrowser);

		//alert(" Browser List Count Before Delete:  " + this._browserList.length + " at Index:  " + browserIndex);
		
    	if (browserIndex > -1)
    	{
			this._browserList.splice(browserIndex, 1);
		}
	},
	
	/**
	 * Remove aLoadHost from uri list
	 * @param {String} aLoadHost
	 */
	removeHost: function(aLoadHost)
	{
		if (this.containsHost(aLoadHost))
		{
			//alert("uriList contains " + aLoadHost);
			
			if (!this._cm.utils.isUrlMultipleTabs(aLoadHost, true))
			{
				//alert(aLoadHost + " only open in one tab, so deleting host");	
				delete this._uriList[aLoadHost];				
			}
		}
	}
}
