/**
 * Retrieve cookie information for the current URL
 * @type cookieMonster_CookieInfo
 */
s1tony.CM.cookieInfo =
{
    choice: null,
    _bundle: null,
    _isExactPerm: false,
    _isEffectiveTLDService: false,
    _tempAllowList: null,
    _globalOverrideList: null,

    init: function()
    {
        // Declare instance of cookie permission and
        // query an nsICookiePermission interface
        this.choice = Components.classes["@mozilla.org/cookie/permission;1"].createInstance();
        this.choice.QueryInterface(Components.interfaces.nsICookiePermission);

        this._bundle = document.getElementById("cookie-menu-labels");
        
        // Check if the method testExactPermission is available
        // in the version of the Moz engine being used
        // Note:  Currently, testExactPermission is not available
        // in Moz 1.8 (FF2), but is available in Moz 1.9 (FF3)
        var accessString = CM_COOKIE_ACCESS_DEFAULT;
        var permissionManager = Components.classes["@mozilla.org/permissionmanager;1"]
            .getService(Components.interfaces.nsIPermissionManager);
        if (permissionManager.testExactPermission)
        {
        	this._isExactPerm = true;
        }
 
        // Check if the service nsIEffectiveTLDService is available
        // in the version of the Moz engine being used
        // Note:  Currently, testExactPermission is not available
        // in Moz 1.8 (FF2), but is available in Moz 1.9 (FF3)
        if (Components.classes["@mozilla.org/network/effective-tld-service;1"])
        {
        	this._isEffectiveTLDService = true;
        }
        
		// Initialize TempAllow
        s1tony.CM.tempAllow.init();
		
        // Check if CM_PREFERENCE_TYPE_GLOBAL_OVERRIDE contains
        // any URLs and if so, add to _globalOverrideList
        this._globalOverrideList = s1tony.CM.nsPreferences.getStringPrefArray(CM_PREFERENCE_TYPE_GLOBAL_OVERRIDE);
    },

    isExactPermissions: function()
    {
    	return this._isExactPerm;
    },

    getGlobalOverrideList: function()
    {
    	return this._globalOverrideList;
    },

    setGlobalOverrideList: function()
    {
        this._globalOverrideList = s1tony.CM.nsPreferences.getStringPrefArray(CM_PREFERENCE_TYPE_GLOBAL_OVERRIDE);
    },
    
    // Check the cookie access level for the URI and
    // return this value
    checkCookieAccess:  function(aRequest, aURI)
    {
        aRequest.QueryInterface(Components.interfaces.nsIChannel);

        return this.choice.canAccess(aURI , aRequest.originalURI , aRequest);
    },

    // Check the cookie access level for the URI and
    // return a string representation of this value
    checkCookieAccessString:  function(aRequest, aURI)
    {
        var accessString = CM_COOKIE_ACCESS_DEFAULT;

        aRequest.QueryInterface(Components.interfaces.nsIChannel);

        switch (this.choice.canAccess(aURI , aRequest.originalURI , aRequest))
        {
            case CM_CA_LEVEL_DEFAULT:
                accessString = CM_COOKIE_ACCESS_DEFAULT;
                break;
            case nsIPermissionManager.ALLOW_ACTION:
                accessString = CM_COOKIE_ACCESS_ALLOW;
                break;
            case nsIPermissionManager.DENY_ACTION:
                accessString = CM_COOKIE_ACCESS_DENY;
                break;
            case nsICookiePermission.ACCESS_SESSION:
                accessString = CM_COOKIE_ACCESS_SESSION;
                break;
            default:
                accessString = CM_COOKIE_ACCESS_DEFAULT;
                break;
        }

        return accessString;
    },

    // Check the permission access level for the URI and
    // return a string representation of this value
    checkPermissionString:  function(aURI, aType)
    {
        var accessString = CM_COOKIE_ACCESS_DEFAULT;
        var permissionManager = Components.classes["@mozilla.org/permissionmanager;1"]
            .getService(Components.interfaces.nsIPermissionManager);

        switch (permissionManager.testPermission(aURI ,aType))
        {
            case 0:
                accessString = CM_COOKIE_ACCESS_DEFAULT;
                break;
            case nsIPermissionManager.ALLOW_ACTION:
                accessString = CM_COOKIE_ACCESS_ALLOW;
                break;
            case nsIPermissionManager.DENY_ACTION:
                accessString = CM_COOKIE_ACCESS_DENY;
                break;
            case nsICookiePermission.ACCESS_SESSION:
                accessString = CM_COOKIE_ACCESS_SESSION;
                break;
            default:
                accessString = CM_COOKIE_ACCESS_DEFAULT;
                break;
        }

        return accessString;
    },

    // Check the exact permission access level for the URI and
    // return an array of string representation of the values
    // for both the top level and 2nd level domain,
    // plus a standard testPermission on the URI
    // testExactPermission requires an exact hostname match - subdomains are not a match
    checkPermissionArray:  function(aURI, aType)
    {
        var accessStringTop = CM_COOKIE_ACCESS_DEFAULT;
        var accessStringSecond = CM_COOKIE_ACCESS_DEFAULT;
        var accessString = CM_COOKIE_ACCESS_DEFAULT;
        var accessArray = new Array(accessStringTop, accessStringSecond, accessString);
        var secondURI  = this.getSecondLevelURI(aURI);
        var tempURIIndex = -1;

        var permissionManager = Components.classes["@mozilla.org/permissionmanager;1"]
            .getService(Components.interfaces.nsIPermissionManager);
        
        // Determine what test permission method to use based
        // on the value of _isExactPermission
        if (this._isExactPerm)
        {
	        // Top level domain
	        switch (permissionManager.testExactPermission(aURI ,aType))
	        {
	            case CM_CA_LEVEL_DEFAULT:
	                accessStringTop = CM_COOKIE_ACCESS_DEFAULT;
	                break;
	            case nsIPermissionManager.ALLOW_ACTION:
	                accessStringTop = CM_COOKIE_ACCESS_ALLOW;
	                break;
	            case nsIPermissionManager.DENY_ACTION:
	                accessStringTop = CM_COOKIE_ACCESS_DENY;
	                break;
	            case nsICookiePermission.ACCESS_SESSION:
	                accessStringTop = CM_COOKIE_ACCESS_SESSION;
	                break;
	            default:
	                accessStringTop = CM_COOKIE_ACCESS_DEFAULT;
	                break;
	        }
	
	        // Second level domain
	        switch (permissionManager.testExactPermission(secondURI ,aType))
	        {
	            case CM_CA_LEVEL_DEFAULT:
	                accessStringSecond = CM_COOKIE_ACCESS_DEFAULT;
	                break;
	            case nsIPermissionManager.ALLOW_ACTION:
	                accessStringSecond = CM_COOKIE_ACCESS_ALLOW;
	                break;
	            case nsIPermissionManager.DENY_ACTION:
	                accessStringSecond = CM_COOKIE_ACCESS_DENY;
	                break;
	            case nsICookiePermission.ACCESS_SESSION:
	                accessStringSecond = CM_COOKIE_ACCESS_SESSION;
	                break;
	            default:
	                accessStringSecond = CM_COOKIE_ACCESS_DEFAULT;
	                break;
	        }        	
        }
        else
        {
	        // Second level domain
	        switch (permissionManager.testPermission(secondURI ,aType))
	        {
	            case CM_CA_LEVEL_DEFAULT:
	                accessStringSecond = CM_COOKIE_ACCESS_DEFAULT;
	                break;
	            case nsIPermissionManager.ALLOW_ACTION:
	                accessStringSecond = CM_COOKIE_ACCESS_ALLOW;
	                break;
	            case nsIPermissionManager.DENY_ACTION:
	                accessStringSecond = CM_COOKIE_ACCESS_DENY;
	                break;
	            case nsICookiePermission.ACCESS_SESSION:
	                accessStringSecond = CM_COOKIE_ACCESS_SESSION;
	                break;
	            default:
	                accessStringSecond = CM_COOKIE_ACCESS_DEFAULT;
	                break;
	        }
	        
	        // Top level domain
	        switch (permissionManager.testPermission(aURI ,aType))
	        {
	            case CM_CA_LEVEL_DEFAULT:
	                accessStringTop = CM_COOKIE_ACCESS_DEFAULT;
	                break;
	            case nsIPermissionManager.ALLOW_ACTION:
	                accessStringTop = CM_COOKIE_ACCESS_ALLOW;
	                break;
	            case nsIPermissionManager.DENY_ACTION:
	                accessStringTop = CM_COOKIE_ACCESS_DENY;
	                break;
	            case nsICookiePermission.ACCESS_SESSION:
	                accessStringTop = CM_COOKIE_ACCESS_SESSION;
	                break;
	            default:
	                accessStringTop = CM_COOKIE_ACCESS_DEFAULT;
	                break;
	        }
        }

        // Standard testPermission for URI (End Result)
        switch (permissionManager.testPermission(aURI ,aType))
        {
            case CM_CA_LEVEL_DEFAULT:
                accessString = CM_COOKIE_ACCESS_DEFAULT;
                break;
            case nsIPermissionManager.ALLOW_ACTION:
                accessString = CM_COOKIE_ACCESS_ALLOW;
                break;
            case nsIPermissionManager.DENY_ACTION:
                accessString = CM_COOKIE_ACCESS_DENY;
                break;
            case nsICookiePermission.ACCESS_SESSION:
                accessString = CM_COOKIE_ACCESS_SESSION;
                break;
            default:
                accessString = CM_COOKIE_ACCESS_DEFAULT;
                break;
        }

        // Lastly check to see if this is a temporary permission
        //tempURIIndex = this._tempAllowList.indexOf(aURI.asciiHost);
        //if (tempURIIndex > -1)
        if (s1tony.CM.tempAllow.isTempPermission(aURI))
        {       
        	accessStringTop = CM_COOKIE_ACCESS_TEMP_ALLOW;
        	accessString = CM_COOKIE_ACCESS_TEMP_ALLOW;
        }

        //tempURIIndex = this._tempAllowList.indexOf(secondURI.asciiHost);
        //if (tempURIIndex > -1)
        if (s1tony.CM.tempAllow.isTempPermission(secondURI))
        {       
        	accessStringSecond = CM_COOKIE_ACCESS_TEMP_ALLOW;
        	accessString = CM_COOKIE_ACCESS_TEMP_ALLOW;
        	
        	// If not ExactPerm and second level is temporary,
        	// then if top level is allow, change to temporary
        	// because any cookies will be deleted upon exit
	        if (!this._isExactPerm && (accessStringTop == CM_COOKIE_ACCESS_ALLOW))
	        {
        		accessStringTop = CM_COOKIE_ACCESS_TEMP_ALLOW;	      		
	        }
        }
        
        accessArray[CM_TOP_LEVEL] = accessStringTop;
        accessArray[CM_SECOND_LEVEL] = accessStringSecond;
        accessArray[CM_URL_STANDARD_LEVEL] = accessString;
        
        return accessArray;
    },

    // Input the numeric permission level and
    // return a string representation of this value
    getPermissionString:  function(aValue)
    {
        var accessString = CM_COOKIE_ACCESS_DEFAULT;

        switch (aValue*1)
        {
            case CM_CA_LEVEL_DEFAULT:
                accessString = CM_COOKIE_ACCESS_DEFAULT;
                break;
            case nsIPermissionManager.ALLOW_ACTION:
                accessString = CM_COOKIE_ACCESS_ALLOW;
                break;
            case nsIPermissionManager.DENY_ACTION:
                accessString = CM_COOKIE_ACCESS_DENY;
                break;
            case nsICookiePermission.ACCESS_SESSION:
                accessString = CM_COOKIE_ACCESS_SESSION;
                break;
            case CM_CA_LEVEL_TEMP_ALLOW:
                accessString = CM_COOKIE_ACCESS_TEMP_ALLOW;
                break;
            default:
                accessString = CM_COOKIE_ACCESS_DEFAULT;
                break;
        }

        return accessString;
    },

    // Input the string representation
    // of the permission level and
    // return the numeric representation of this value
    getPermissionValue:  function(aValue)
    {
        var accessValue = CM_CA_LEVEL_DEFAULT;

        switch (aValue)
        {
            case CM_COOKIE_ACCESS_DEFAULT:
                accessValue = CM_CA_LEVEL_DEFAULT;
                break;
            case CM_COOKIE_ACCESS_ALLOW:
                accessValue = nsIPermissionManager.ALLOW_ACTION;
                break;
            case CM_COOKIE_ACCESS_DENY:
                accessValue = nsIPermissionManager.DENY_ACTION;
                break;
            case CM_COOKIE_ACCESS_SESSION:
                accessValue = nsICookiePermission.ACCESS_SESSION;
                break;
            case CM_COOKIE_ACCESS_TEMP_ALLOW:
                accessValue = CM_CA_LEVEL_TEMP_ALLOW;
                break;
            default:
                accessValue = CM_CA_LEVEL_DEFAULT;
                break;
        }

        return accessValue;
    },

    // Set override for hosts cookie access
    setCookieAccess: function(aURI, aAccess, aDomainType)
    {
        var hostURI = null;
        var accessLevel = null;
        var tempHostIndex = -1;

        if (aDomainType == CM_SECOND_LEVEL)
        {
            hostURI = this.getSecondLevelURI(aURI);
        }
        else
        {
        	hostURI = aURI;
        }

        // Check if temporary access
        if (aAccess == CM_CA_LEVEL_TEMP_ALLOW)
        {
        	// Check if URI already has a non-default cookie access
        	s1tony.CM.tempAllow.add(hostURI);
        	aAccess = nsIPermissionManager.ALLOW_ACTION;
        }
        else if (s1tony.CM.tempAllow.isTempPermission(hostURI))
    	{
    		s1tony.CM.tempAllow.remove(hostURI);
    		
    		// If the updated permission is Deny or Default, where Default
    		// is Deny, then delete any cookies set for this host
	        if ((aAccess == nsIPermissionManager.DENY_ACTION) ||
	            ((aAccess == 0) && (s1tony.CM.prefObserver.getCookiePrefString() == this._bundle.getString("rejected"))))
	        {
	        	//alert("aAccess = " + aAccess);
		    	// Set aUseBaseDomain to true
		        this.deleteHostCookies(aURI.asciiHost, true);
	        }        		
        }
        
        this.choice.setAccess(hostURI, aAccess);

        // If new access is deny and the preference
        // deletecookiesondeny is true
        // then delete existing cookies for this host
        if ((aAccess == nsIPermissionManager.DENY_ACTION) &&
            s1tony.CM.nsPreferences.getBoolPref("deletecookiesondeny", false))
        {
            this.deleteHostCookies(hostURI.host, false);
        }
    },

    // Convert URI to Second Level Domain
    // (i.e. groups.yahoo.com to yahoo.com)
    getSecondLevelURI: function(aURI)
    {
        // Parse the host string
        var hostString = aURI.asciiHost;
        var newHostString = null;
        var newHost = aURI;

        newHostString = this.getSecondLevelHost(hostString);
        newHost = s1tony.CM.utils.createURIFromHostName(newHostString);
        
        return newHost;
    },

    // Convert Host String to Second Level Domain
    // (i.e. groups.yahoo.com to yahoo.com)
    getSecondLevelHost: function(aHost)
    {
        // Parse the host string
        var checkExp = /^com|^net|^org|^edu/i;
        var checkSpecialTwo = /^au|^uk|^tw|^br/i;
        var newHostString = null;

        // First check if IPv6
		if (aHost.split(":").length > 1)
		{
			// We're probably ipv6
			newHostString = "["+ aHost +"]";
		}	
        else if (this._isEffectiveTLDService)
        {
        	// Is the effective-tld-service available
        	try
        	{
	 	 		var eTLDService = Components.classes["@mozilla.org/network/effective-tld-service;1"]
		                  .getService(Components.interfaces.nsIEffectiveTLDService);
				
		 		newHostString = eTLDService.getBaseDomainFromHost(aHost);       		
        	}
        	catch(e)
	        {
	        	newHostString = aHost;
	        }   
        }
        else
        {
	        // Is this the special case where
	        // the URI ends in two characters
	        var hostParts = aHost.split(".");
	
	        // Do not parse if hostParts.length < 3
	        if (hostParts.length >= 3)
	        {
	            // Normal URI
	            if (hostParts[hostParts.length - 1].length > 2)
	            {
	                newHostString = hostParts[hostParts.length - 2] + "." +
	                    hostParts[hostParts.length - 1];
	            }
	            // Check to see if special
	            // (e.g. www.domain.com.au)/com|net|org|edu/
	            else if((checkExp.test(hostParts[hostParts.length - 2]) &&
	                hostParts[hostParts.length - 1].length <= 2) ||
	                checkSpecialTwo.test(hostParts[hostParts.length - 1]))
	            {
	
	                newHostString = hostParts[hostParts.length - 3] + "." +
	                    hostParts[hostParts.length - 2] + "." +
	                    hostParts[hostParts.length - 1];
	            }
	            else
	            {
	                newHostString = hostParts[hostParts.length - 2] + "." +
	                    hostParts[hostParts.length - 1];
	            }
	        }
	        else
	        {
	            newHostString = aHost;
	        }        	
        }
        
        return newHostString;
    },

    // Get Override Global cookie permissions for URI
    checkOverrideGlobal: function(aURI)
    {
    	var overrideArray = new Array(false, false);
    	var secondURI  = this.getSecondLevelURI(aURI);
    	var tempURIIndex = -1;
        
        // Check both top level and second level URI's
        tempURIIndex = this._globalOverrideList.indexOf(aURI.asciiHost);
        overrideArray[CM_TOP_LEVEL] = (tempURIIndex > -1);

        tempURIIndex = this._globalOverrideList.indexOf(secondURI.asciiHost);
        overrideArray[CM_SECOND_LEVEL] = (tempURIIndex > -1);
        
        return overrideArray;
    },
    
    // Add URI asciihost to Override Global cookie permissions list
    addOverrideGlobal: function(aHost, aDomainType)
    {
		var hostDomain = aHost;
        if (aDomainType == CM_SECOND_LEVEL)
        {
            hostDomain = this.getSecondLevelHost(aHost);
        }

        this._globalOverrideList.push(hostDomain);
        s1tony.CM.nsPreferences.setAppendToStringPref(CM_PREFERENCE_TYPE_GLOBAL_OVERRIDE, hostDomain);    	
    },

    // Remove URI asciihost from Override Global cookie permissions list
    removeOverrideGlobal: function(aHost, aDomainType)
    {
		var hostDomain = aHost;
        var overrideHostIndex = -1;
        
        if (aDomainType == CM_SECOND_LEVEL)
        {
            hostDomain = this.getSecondLevelHost(aHost);
        }

    	overrideHostIndex = this._globalOverrideList.indexOf(hostDomain);
    	if (overrideHostIndex > -1)
    	{
    		this._globalOverrideList.splice(overrideHostIndex, 1);
    		s1tony.CM.nsPreferences.setStringPrefArray(CM_PREFERENCE_TYPE_GLOBAL_OVERRIDE, this._globalOverrideList);      		
    	}  	
    },

    // Remove all URI asciihosts from Override Global cookie permissions list
    removeAllOverrideGlobal: function()
    {
    	this._globalOverrideList = new Array();
    	s1tony.CM.nsPreferences.clearUserPref(CM_PREFERENCE_TYPE_GLOBAL_OVERRIDE);
    	
    	// Reset any global override permissions in place
    	s1tony.CM.cookieMonster.extResetGlobalCookiePref();
    },
    
    // Delete cookies from host
    deleteHostCookies: function(aHost, aUseBaseDomain)
    {
    	var deleteHost = aHost;
        var cookieManager = Components.classes["@mozilla.org/cookiemanager;1"]
            .getService(Components.interfaces.nsICookieManager);

        // If checking 2nd level domain names, make sure
        // deleteHost is a 2nd level domain of aHost
        if (aUseBaseDomain)
        {
        	deleteHost = this.getSecondLevelHost(aHost);
        }
        
        var iter = cookieManager.enumerator;
        while (iter.hasMoreElements())
        {
            var cookie = iter.getNext();

            if (cookie instanceof Components.interfaces.nsICookie)
            {
                // Delete cookies matching aHost
                var cookieHost = (cookie.host.charAt(0) == ".") ? cookie.host.substring(1,cookie.host.length) : cookie.host;

                // If checking 2nd level domain names, make sure
    			// cookieHost is a 2nd level domain of the cookie
        		if (aUseBaseDomain)
        		{
        			cookieHost = this.getSecondLevelHost(cookieHost);
        		}

                if (cookieHost == deleteHost)
                {
                    //alert("Delete: " + cookie.host);
                    cookieManager.remove(cookie.host , cookie.name , cookie.path , 0);
                }
            }
        }
    }
}
