/** 
* cookie script for interfaces needing to set & read multiple values
* cookie script based on O'reilly Definitive javascript. 
* modified to remember cookie set info, assignment of key/vals and store with same method, assignment
* of multiple key/val pairs, true/false tests for cookie
*/

/**
*getCookie and store vals in object
*remember name, daysToLive, path, domain, secure 
*/
function CookieManager(name, daysToLive, path, domain, secure) {
	
	//confirm can read/set cookie
	if(!CookieManager.enabled()){return;}
	
    this.$name = name;  
	this.$daysToLive = daysToLive || false;
	this.$path = path || false;
	this.$domain = domain || false;
	this.$secure = secure || false;
	
	this.getCookie();
} 

CookieManager.prototype.getCookie = function() {
	var allcookies, cookies, cookie, cookieval;
	allcookies = document.cookie;
    if(allcookies === "") {return;}

    // check for name in string of all cookies
    cookies = allcookies.split(';');
    cookie = null;
	
	for(var i = 0; i < cookies.length; i++) {
		if (cookies[i].match(this.$name + "=")){
			cookie = cookies[i];
			//ie adds white space before each cookie
			cookie = cookie.replace(/^\s/, '');
			this.$exists = true;
            break;
        }
    }
    // if no matching cookie, quit now
    if (cookie === null) {
		//or error message
		this.$exists = false;
		return;
	}
	//remove leading &
    cookieval = cookie.substring(this.$name.length+2);
	//for newly initialised cookie
	if(!cookieval.match('&')){return;}
	
	var a = cookieval.split('&');    // array of name/value pairs
	for(var j=0; j < a.length; j++) { // break each pair into an array
		a[j] = a[j].split(':');
		//set the names and values as properties of this Cookie object
		this[a[j][0]] = decodeURIComponent(a[j][1]);
	}
 };

/**
*daysToLive, path, domain, secure are assigned when the cookie object is instantiated
*arguments - 0, 1, or 2 arguments
*0 arguments =  write cookie with already stored values
*1 argument = obj of key value pairs to store
*2 arguments = a single key value pair
*all key val pairs  inc. object properties, values should be strings
*/
CookieManager.prototype.setCookie = function() {
	var args, key, value, obj, cookie, expires, cookieval;
	
	args = arguments.length;	
		if(args === 2){
			key = arguments[0];
			value = arguments[1];
			//check if key/val pair
			if(key && (key !== '') && (typeof key === 'string') && value && (value !== '')){
			    this[key] = value;
		    }
			else{
				throw "Invalid arguments. Expected pairs of key value strings";
			}
	    }
	
		else if(args ===1){
		     obj= arguments[0];
			//check if Object
			if(obj.constructor !== Object){
				throw "Invalid argument. Expected Object containing properties and values, not a " + arguments[0].constructor;
			}
			for(var i in obj){
				this[i] = obj[i];
			}
		}
		//check if too many arguments
		else if(args > 2){ 
			throw "Too many arguments. Multiple key value pairs must be handled via an object";
		}

	//construct cookie from Cookie object properties
	cookieval = "";
	
	for(var prop in this) {
		// Ignore properties with names that begin with '$' and also methods
		if ((prop.charAt(0) === '$') || ((typeof this[prop]) === 'function')){ 
			continue;
		}
		   cookieval = cookieval + '&' + prop + ':' + encodeURIComponent(this[prop]);
	}
	if(cookieval === ''){cookie = this.$name;}
	else{ cookie = this.$name + '=' + cookieval; }
		//expires = deprecated, but max-age not supported by ie
		if (this.$daysToLive) { 
			var date = new Date();
			date.setTime(date.getTime()+(this.$daysToLive*24*60*60*1000));
			expires = "; expires=" + date.toGMTString();
		}
		else {expires = "";}
		cookie += expires;
		if (this.$path) {cookie += "; path=" + this.$path;}
		if (this.$domain){ cookie += "; domain=" + this.$domain;}
		if (this.$secure){ cookie += "; secure";}
		//store the cookie
		document.cookie = cookie;
	
};

/**
 * delete properties of the Object, and remove the cookie
 * removing a cookie requires the same (path, domain, secure) values passed to setCookie().
 */
CookieManager.prototype.remove = function() {
    // Delete the properties of the Cookie object
    for(var prop in this) {
        if (prop.charAt(0) !== '$' && typeof this[prop] !== 'function'){ 
            delete this[prop];
		}
    }
	//note, the stored persistent time is overwritten
	//could write value directly rather than store
	this.$daysToLive = -1;
    this.setCookie( );
};

//read the value of a key
CookieManager.prototype.readKey = function(key){
	if(key){
		return this[key];
	}
};

// remove subkey
CookieManager.prototype.removeKey = function() {
	for(var i=0; i< arguments.length; i++){
		key = arguments[i];
		if((key !== '') && (typeof key === 'string')){
			if(this[key]){
				delete this[key];
			}
		}
	}
	
    this.setCookie();
};

/**
 * static method attempts to determine whether cookies are enabled.
 * It returns true if they appear to be enabled and false otherwise.
 * A return value of true does not guarantee that cookies actually persist.
 * Nonpersistent session cookies may still work even if this method 
 * returns false. 
 */
CookieManager.enabled = function() {
    // Use navigator.cookieEnabled if this browser defines it
    if (navigator.cookieEnabled !== undefined) {
	     return navigator.cookieEnabled;
  	}

    // If we've already cached a value, use that value
    if (CookieManager.enabled.cache !== undefined) {
		return CookieManager.enabled.cache;
  	}

    // Otherwise, create a test cookie with a lifetime
    document.cookie = "testcookie=test";
   
    // Now see if that cookie was saved
    var cookies = document.cookie;
    if (cookies.indexOf("testcookie=test") === -1) {
        return CookieManager.enabled.cache = false;
    }
    else {
        // delete test cookie
		document.cookie = "testcookie=test; expires=Thu, 01-Jan-1970 00:00:01 GMT";
        return CookieManager.enabled.cache = true;
    }
};

//alt to checking for value, scope for confusion? ie. value from object not cookie
CookieManager.prototype.exists = function(key){
	if(key in this){ return true;}
	else {return false;}
};

/**
* strings, to serialise into a set of keyvals for saving sets of information, ie. nested subkeys.
*/
CookieManager.prototype.keySet = function(){
	var setVal='', key;
	for(var i=0; i< arguments.length; i++){
		key = arguments[i];
		if((key !== '') && (typeof key === 'string')){
			if(this[key]){
				setVal += '@' + key + '-' + this[key];
			}
		}
	}

	return setVal;
};

/**
* diagnostic - return cookie properties as string
*/
CookieManager.prototype.cookieVals = function(){
	var cookieProps='';
	for(var i in this){
	    if((typeof this[i]) !== 'function'){
	       cookieProps += i + '=' + this[i] + '\n';
	    }
	}
	return cookieProps;
}

/**
* generic event function
*/
function addEvent(obj,evt,fn){
	if(obj.addEventListener){
		obj.addEventListener(evt, fn, false);
	}
	else if(obj.attachEvent){
		obj.attachEvent('on' + evt,fn);
	}
}

