var Utilities = (function()
{
	var window = this,
		utilities = 
		{ 
			QueryString: (function(
				queryString)
			{
				var queryStringKeyValues = [];
				var keyValueRegex = /([\w-]+)=([\w-]+)/;

				var match = keyValueRegex.exec(
					queryString);

				queryStringKeyValues.length = 0;

				while ((match) &&
					(match.length > 0))
				{
					queryStringKeyValues[match[1]] = match[2];

					queryStringKeyValues.length++;

					match = keyValueRegex.exec(RegExp.rightContext);
				}
				
				return queryStringKeyValues;
			})(document.location.search),
			QueryStringDataBuilder: function()
			{
				var queryStringData = [];

				this.length = function()
				{
					return queryStringData.length;
				}

				this.append = function(
					key,
					value)
				{
					queryStringData.push(
						encodeURIComponent(
							key) +
						'=' +
						encodeURIComponent(
							value));
				};

				this.toString = function()
				{
					return (
						queryStringData.join('&'));
				};
			},
			Base64: 
			{
				e: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_|",
				encode: function(input)
				{
					var output = '';
					var chr1, chr2, chr3;
					var enc1, enc2, enc3, enc4;
					var i = 0;

					do
					{
						chr1 = input.charCodeAt(i++);
						chr2 = input.charCodeAt(i++);
						chr3 = input.charCodeAt(i++);
						enc1 = chr1 >> 2;
						enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
						enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
						enc4 = chr3 & 63;

						if (isNaN(chr2))
						{
							enc3 = enc4 = 64;
						}
						else if (isNaN(chr3))
						{
							enc4 = 64;
						}

						output = (
							output +
							utilities.Base64.e.charAt(enc1) +
							utilities.Base64.e.charAt(enc2) +
							utilities.Base64.e.charAt(enc3) +
							utilities.Base64.e.charAt(enc4));
					}
					while (i < input.length);

					return output;
				}
			}
		};

	return utilities;
})();