/* -------------------------------------------------------------------------- */
/** 
 *    @fileoverview
 *       cookie read/write controller.
 *
 *    @version rev012a.2007-10-11
 *    @requires json.js
 */
/* -------------------------------------------------------------------------- */



/* --------------- Constructor : BACookie --------------- */
/**
 * constructor of cookie controller.
 * @class cookie controller
 * @param {String}  cookieName    name of cookie to treat in this instance (required)
 * @param {Date}    expires       expiring date of the cookie
 * @param {Date}    expires       num of days to expire the cookie
 * @param {String}  path          cookie readable path
 * @param {String}  domain        cookie readable domain
 * @param {Boolean} secure        cookie r/w in HTTPS session only
 * @constructor
 */
function BACookie(cookieName, expires, path, domain, secure) {
	var alen = arguments.length;
	if (typeof cookieName != 'string' || cookieName == '') {
		throw 'BACookie: argument \'cookieName\' must be a significant string.';
	}
	if (alen >= 2 && (typeof expires != 'number' || expires < 0) && (!expires || expires.constructor != Date)) {
		throw 'BACookie: argument \'expires\' must be a Date instance or a positive number.';
	}
	if (alen >= 3 && typeof path != 'string') {
		throw 'BACookie: argument \'path\' must be a string';
	}
	if (alen >= 4 && typeof domain != 'string') {
		throw 'BACookie: argument \'domain\' must be a string';
	}
	if (alen >= 5 && typeof secure != 'boolean') {
		throw 'BACookie: argument \'secure\' must be a boolean (true/false)';
	}
	if (typeof expires == 'number' && expires > 0) {
		var d = new Date();
		d.setDate(d.getDate() + expires);
		expires = d;
	}

	/** name of cookie which is treated by this instance.
	    @type String @private */
	this.cookieName = cookieName;
	/** expiring date of the cookie.
	    @type Date @private */
	this.expires    = expires || null;
	/** specify cookie readable path.
	    @type String @private */
	this.path       = path    || '';
	/** specify cookie readable domain.
	    @type String @private */
	this.domain     = domain  || '';
	/** cookie r/w in HTTPS session only
	    @type Boolean @private */
	this.secure     = (typeof secure == 'boolean') ? secure : false;

	if (typeof(dataCompressor) == "function") {
		this.compressor = new dataCompressor;
	}
}

/**
 * get cookie data.
 * @return JSON-formed object if cookie value is a JSON-string, else return cookie value as string.
 * @type Object/String
 */
BACookie.prototype.get = function() {
	var cookies   = this.getCookies();
	var cookieStr = '';
	var ret;
	for (var i = 0, n = cookies.length; i < n; i++) {
		if (cookies[i].key == this.cookieName) {
			cookieStr = unescape(cookies[i].value);
			break;
		}
	}
	try {
		// convert cookieStr to a JSON-formed object.
		ret = (new BAJsonObject(cookieStr)).get();
	} catch(err) {
		// cookieStr is a normal string (not a JSON-formed string).
		ret = cookieStr || null;
	}
	return ret;

}

/**
 * set cookie data.
 * @param {String} arg    primitive string to set cookie
 * @param {Object} arg    JSON-formed object to set cookie
 * @return cookie string
 * @type String
 */
BACookie.prototype.set = function(arg) {
	var str;
	switch(typeof arg) {
		case 'object' : str = (new BAJsonObject(arg)).toString(); break;
		case 'string' : str = arg;                                break;
		default       : throw 'BACookie.set: first argument must be an object or a string.';
	}
	var cookie = this.bakeCookie(str);
	document.cookie = cookie;
	return (decodeURI) ? decodeURI(cookie) : unescape(cookie);
}

/**
 * erase cookie from the browser.
 * @return cookie string
 * @type String
 */
BACookie.prototype.erase = function() {
	var expires = new Date();
	expires.setDate(expires.getDate() - 1);
	var cookie = this.bakeCookie('', expires);
	document.cookie = cookie;
	return unescape(cookie);
}

/**
 * get cookies from the browser.
 * @return an array of 'key/value' associative arrays generated from the browser cookie.
 * @type Array
 * @private
 */
BACookie.prototype.getCookies = function () {
	var pairs   = [];
	var cookies = document.cookie.split(/; ?/);
	for (var i = 0, n = cookies.length; i < n; i++) {
		var part = cookies[i];
		var key   = (part.indexOf("=") > -1) ? part.substr(0, part.indexOf("=")) : '';//pair[0];
		var value = (part.indexOf("=") > -1) ? part.substr(part.indexOf("=") + 1) : '';
		if (this.compressor && key != "s_sq" && key != "s_cc") value = this.compressor.decompress(value);
		if (key) {
			pairs[pairs.length] = { key : key, value : value };
		}
	}
	return pairs;
}

/**
 * create cookie string.
 * @param {String} cookieStr    cookie string to set
 * @param {Date}   expires      day to expire the cookie
 * @return created cookie string
 * @type String
 * @private
 */
BACookie.prototype.bakeCookie = function(cookieStr, expires) {
	if (typeof cookieStr != 'string') {
		cookieStr = '';
	}
	expires = (expires && expires.constructor == Date) ? expires : this.expires;
	if (this.compressor) cookieStr = this.compressor.compress(cookieStr);
	var cookie = this.cookieName + '='
	           + ((encodeURI) ? encodeURI(cookieStr) : escape(cookieStr))
	           + (expires     ? '; expires=' + expires.toGMTString() : '')
	           + (this.path   ? '; path='    + this.path             : '')
	           + (this.domain ? '; domain='  + this.domain           : '')
	           + (this.secure ? '; secure'                           : '');
	return cookie;
}

