/******************************************************************************\

	Title: jQuery Cookie Module
	Author: Chase Mathewson
	Licence: http://creativecommons.org/licenses/by-sa/3.0/
	Requires: "json2.js" http://www.json.org/
	
	Adds an API for accessing, editing, and removing cookies from your page.
	
		$.cookie() :Object
			Returns an object containing all of the site's cookies.
			
		$.cookie( name:String ) :Object
			Returns a cookie's value.
			
		$.cookie( name:String, value:Object ) :CookieModule
			Sets a value for a cookie. Returns self.
			
		$.cookie( map:Object ) :CookieModule
			Sets a value for a cookie by using the passed map. Returns self.
			
		$.cookie.get( name:String ) :Object
			Returns a value containing the cookie set under a named key.
			
		$.cookie.set( name:String ) :Object
			Sets a value for a cookie. Returns self.
			
		$.cookie.set( map:Object ) :CookieModule
			Sets a value for cookies by using the passed map. Returns self.
			
		$.cookie.remove( name:String ) :CookieModule
			Removes a cookie. Returns self.
			
		$.cookie.clear( name:String ) :CookieModule
			Removes all site cookies. Returns self.
	
\******************************************************************************/

(function($, undefined) {
	
	//dependancy check
	if (!JSON) throw new Error('JSON support is required.');
	
/** Private Variables *********************************************************/
	
var cookiePattern = /^\s*(.+)=(.+)\s*/;
var objectPattern = /^\[object\s(.*)\]$/;
var leadingWhitespace = /^\s*/;
	
/** Private Functions *********************************************************/

//determines the type of data
function type(obj, typestr) {
	if (obj === undefined) return 'undefined';
	if (obj === null) return 'null';
	var string = Object.prototype.toString.call(obj);
	var name = string.match(objectPattern)[1];
	return typestr ? name.toLowerCase() === typestr : name.toLowerCase();
};


//retrieve a cookie value by name
function getCookie(name){
	var property = name + "=";
	var cookies = document.cookie.split(';');
	for (var cookie, i = 0; i < cookies.length; i++) {
		cookie = cookies[i].replace(/^\s*/g, '');
		if (cookie.indexOf(property) === 0) {
			cookie = cookie.substring(property.length, cookie.length);
			return JSON.parse(cookie);
		}
	}
	return null;
}

//sets a cookie by name and value with days to expire
function setCookie(name, value, days){
	value = JSON.stringify(value);
	var date = new Date();
	date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
	var expiration = '; expires=' + date.toGMTString();
	document.cookie = name + '=' + value + expiration + '; path=/';
}

//removes a cookie
function removeCookie(name){
	setCookie(name, '', -1);
}

//Retrieve all site cookies
function getCookies() {
	var cookies = {};
	var crumbs = document.cookie.split(';');
	var crumb, matches, key, value;
	for (var i = 0; i < crumbs.length; i++) {
		crumb = crumbs[i];
		matches = crumb.match(cookiePattern);
		key = matches[1];
		value = matches[2];
		cookies[key] = JSON.parse(value);
	}
	return cookies;
}

//Assign all site cookies
function setCookies(Object_cookie) {
	for (var c in Object_cookie) {
		setCookie(c, Object_cookie[c]);
	}
}

//removes all cookies
function removeCookies() {
	var cookies = getCookies();
	for (var c in cookies){
		removeCookie(c);
	}
}

/** Create Cookie Module ******************************************************/

$.cookie = function cookie(String_selector, Object_data, Number_days) {
	switch (arguments.length) {
		case 0: return getCookies();
		case 1:
			if (type(String_selector, 'string')) {
				return getCookie(String_selector);
			}
			else {
				setCookies(String_selector);
				break;
			}
		default: 
			setCookie(String_selector, Object_data, Number_days || 14);
	}
	return this;
};

//checks for the existance of a cookie
$.cookie.has = function get(String_selector) {
	return getCookie(String_selector) !== null;
};

//returns the value of a cookie, or all site cookies
$.cookie.get = function get(String_selector) {
	return arguments.length ? getCookie(String_selector) : getCookies();
};

//sets the value of a cookie, or sets cookies for a passed object
$.cookie.set = function set(String_selector, Object_value) {
	if (type(String_selector, 'string')) {
		setCookie(String_selector, Object_value);
	}
	else {
		setCookies(Object_value);
	};
	return this;
};

//removes a cookie
$.cookie.remove = function remove(String_selector) {
	removeCookie(String_selector);
	return this;
};

//removes all cookies
$.cookie.clear = function clear(String_selector) {
	removeCookies();
	return this;
};

})(jQuery);
