(function (iTim) {

	var defaultOptions = {
		name: 'iTimCookieJar',
		path: '/',
		domain: this.location.host.match(/\d+\.\d+.\d+.\d+/) ? this.location.host : this.location.host.replace(/^.*(\.[^.]+\.[^.]+)$/, function (m, d) {
			return d;
		}),
		expires: null,
		maxCookieLength: 3000
	};

	var cookieJar = {
		opt: null,
		cookies: null,
		get: function () {
			return iTim.Json.serialize(this.cookies);
		},
		write: function () {
			var expires = this.opt.expires ? '; Expires=' + this.opt.expires : '';
			var domain = this.opt.domain ? '; Domain=' + this.opt.domain : '';
			var path = this.opt.path ? '; Path=' + this.opt.path : '';
			s = iTim.format('{0}={1}{2}{3}{4}', this.opt.name, this.escape(this.get()), expires, domain, path);
			if (s.length > this.opt.maxCookieLength) {
				throw iTim.format('maximum cookie length of {0} exceeded for cookie jar {1}.', this.opt.maxCookieLength, this.opt.name);
			}
			document.cookie = s;
		},
		erase: function () {
			document.cookie = iTim.format('{0}=; Expires=Thu Jan 01 1970 00:00:00 GMT', this.opt.name);
			this.cookies = {};
		},
		size: function () {
			return this.escape(this.get()).length;
		},
		unescape: function (s) {
			return decodeURIComponent(s);
		},
		escape: function (s) {
			return encodeURIComponent(s);
		},
		load: function () {
			var s = new RegExp(this.opt.name + '=(.*?)(?:;|$)').exec(document.cookie);
			s = (s && s[1]) || '{}';
			this.cookies = iTim.Json.unserialize(this.unescape(s));
			return this;
		},
		init: function (opt) {
			this.opt = opt;
			this.load();
			return this;
		}
	};

	iTim.CookieJar = {
		options: defaultOptions,
		jars: {},
		get: function (opt) {
			opt = iTim.extend({}, defaultOptions, opt || {});
			if (this.jars[opt.name]) {
				return this.jars[opt.name];
			}
			var jar = iTim.object(cookieJar).init(opt);
			this.jars[opt.name] = jar;
			return jar;
		},
		write: function () {
			iTim.each(this.jars, function () {
				this.write();
			});
		}
	};

})(iTim);
