/**
 * Cookie Muncher is a cookie manager.
 *
 * It can lookup the values of existing cookies.
 * It can save individual cookies.
 * It can set the values of individual cookies without storing them.
 * It uses properties and prototypes to save default cookie attributes
 *    (path, domain, expires, secure) so that they don't have to be specified every time.
 * It can set relative expiry date by using simple strings (ex: expires in "10 years").
 * It can decode individual cookie values into an Object and encode it back into a String.
 *
 * @author       sl@fecondcarcan.com -- adjusted for Incysive Media
 * @version      00.00.00U
 *
 * @lastmodified 2003-05-15
 */

/**
 * Constructor for the cookie manager
 *
 * @param vExpires  Expiration date/time of cookie
 * @param sPath     Path within the webserver where the cookie is visible
 * @param sDomain   Domain where the cookie is visible
 * @param bSecure   This cookie is available only via SSL connections IFF bSecure==true
 *
 * @return CookieMuncher Object
 */
function CookieMuncher(vExpires, sPath, sDomain, bSecure) {

    if (vExpires != null) this.expires = vExpires;
    if (this.expires != null) this.expires = this.expire(vExpires);
    if (sPath != null) this.path = sPath;
    if (sDomain != null) this.domain = sDomain;
    if (bSecure != null) this.secure = bSecure;

    this.cookies = this.decode(document.cookie);

    return this;
}

CookieMuncher.prototype.path = null;
CookieMuncher.prototype.domain = null;
CookieMuncher.prototype.expires = "1 month";
CookieMuncher.prototype.secure = false;

/**
 * Returns the value of a Cookie
 *
 * @param sName name of cookie
 * @param vValue Default value
 *
 * @return String value associated to sName; vValue when the name doesn't exist or its value is empty
 */
CookieMuncher.prototype.get = function(sName, vValue) {

    var v = this.cookies[sName];
    return (v != null && v != '') ? v : vValue;

}

/**
 * Sets the value of a Cookie without saving it
 *
 * @param sName name of cookie
 * @param vValue value to set
 *
 * @return String value that has been set
 */
CookieMuncher.prototype.set = function(sName, vValue) {

    return v = this.cookies[sName] = vValue;

}

/**
 * Turns a cookie value into an object
 *
 * @param sName name of cookie
 *
 * @return Object
 */
CookieMuncher.prototype.load = function(sName) {

    return this.decode(this.get(sName));

}

/**
 * Stores a cookie using the current properties
 *
 * @param sName name of cookie to store
 * @param vValue value of cookie to store
 *
 * @return this object
 */
CookieMuncher.prototype.store = function(sName, vValue) {

    if (vValue != null) {
        this.set(sName, vValue);
    } else {
        vValue = this.cookies[sName];
    }

    document.cookie = this.encode(sName, vValue);

    return this;
}

/**
 * Sets the expiration date of this cookie.  Defaults to just before now.
 *
 * @param vExpires (Date or strings) new date or date difference.
 *
 * String format :: number + " " + period, where period in (ye[ars]|mo[nths]|da[ys]|ho[urs]|mi[nutes]|se[conds])
 *
 * @return new expiration date
 */
CookieMuncher.prototype.expire = function(vExpires) {

	if (null != vExpires) {
		if (typeof vExpires == "string" || vExpires.constructor == String) {
			var aDate = vExpires.split(" ");
			var iDelta = Number(aDate[0]);
			var sDatePart = (aDate[1] != null) ? aDate[1].substring(0,2) : "mi";
			vExpires = new Date();
			switch (sDatePart) {
				case "ye": // year
					vExpires.setFullYear(vExpires.getFullYear() + iDelta);
					break;	
				case "mo": // month
					vExpires.setMonth(vExpires.getMonth() + iDelta);
					break;
				case "da": // day
					vExpires.setDate(vExpires.getDate() + iDelta);
					break;	
				case "ho": // hour
					vExpires.setHours(vExpires.getHours() + iDelta);
					break;	
				case "mi": // minute [default]
					vExpires.setMinutes(vExpires.getMinutes() + iDelta);
					break;		
				case "se": // second
					vExpires.setSeconds(vExpires.getSeconds() + iDelta);		
			}
		} 		
	} else {
		vExpires = new Date();
		vExpires.setTime(vExpires.getTime() - 1);
	}
	return this.expires = vExpires;
}

/**
 * Transforms a cookie into a String.
 *
 * @param sName name of cookie to serialize
 * @param vValue String value or Object to encode
 *
 * @return serialized String
 */
CookieMuncher.prototype.encode = function(sName, vValue) {

    if (null == vValue) vValue = "";
    if (typeof vValue == "object") {
        switch (vValue.constructor) {
            case Object:
                 vValue = this.toString(vValue);
            // Add support for other data types here
         }
    }

    var s = sName + "=" + escape(vValue);

    // Expire empty cookies
    var dExpires = this.expires;
    if ('' == vValue || null == vValue) this.expire();
    if (this.expires != null) s +=  "; expires=" + this.expires.toGMTString();
    this.expires = dExpires;

    if (this.path != null) s +=  "; path=" + this.path;
    if (this.domain != null) s +=  "; domain=" + this.domain;
    if (this.secure == true) s +=  "; secure";


    return s;
}

/**
 * Transforms a Cookie string into an addressable object
 *
 * @param s Cookie String
 *
 * @return new Object
 */
CookieMuncher.prototype.decode = function(s) {

    var aFields = s.split('; ');
    var aField, sName, sValue;

    var o = new Object();

    for (var i = 0; i < aFields.length; i++) {
        aField = aFields[i].split('=');
        sName = aField[0];
        sValue = aField[1];
        o[sName] = new String((sValue != null) ? unescape(sValue) : '');
    }

	delete aField;
	delete aFields;

    return o;
}

/**
 * Turns the list of temporary cookies back into a String
 *
 * @param o (optional) Object to turn into a String. Defaults to this.cookies.
 *
 * @return (String) List of cookies
 */
CookieMuncher.prototype.toString = function (o) {

    if (null==o) o = this.cookies;

	var s = '', sSplit = "";
	for (var k in o) {
		if (typeof k != "function" && k != "") {		
			s += sSplit + k + "=" + escape(o[k]);
			sSplit = "; ";
		}
	}
	return s;
}

