function TagCloud(settings) {
	var currentTimestamp = Math.round(new Date().getTime() / 1000);

	var tagSpinner = $("<img/>");
	var imageSpinner = $("<img/>");

	var baseURL = "http://minasgil.dyndns.org/~personaltagcloud/api/proxy.php";
	var args = {
		'func': "selectTags",
		'return': "json",
		'service': settings.service,
		'from': currentTimestamp - settings.period * 3600,
		'apiKey': settings.apiKey,
		'userid': settings.userId
	}

	if(settings.tagCloudAnchor || settings.imageCloudAnchor ) {
		if(settings.tagCloudAnchor) {
			tagSpinner
				.addClass("spinner")
				.css({display: "none"})
				.attr("src", "http://minasgil.dyndns.org/~personaltagcloud/images/spinner.gif")
				.attr("alt", "Loading...")
				.appendTo(settings.tagCloudAnchor)
				.fadeIn("fast");
		}
		if(settings.imageCloudAnchor) {
			imageSpinner
				.addClass("spinner")
				.css({display: "none"})
				.attr("src", "http://minasgil.dyndns.org/~personaltagcloud/images/spinner.gif")
				.attr("alt", "Loading...")
				.appendTo(settings.imageCloudAnchor)
				.fadeIn("fast");
		}
		getData();
	}
	else {
		alert("Error: TagCloud object created but no anchors for either imageCloud or tagCloud was supplied.");
	}

	function getData() {
		var argString = "?";
		for(arg in args) {
			argString += arg + "=" + args[arg] + "&";
		}
		$.getJSON(baseURL + argString + "jsoncallback=?", function(data) {
			if(data.error) {
				alert("Error: " + data.error);
			}
			else {
				if(settings.tagCloudAnchor) {
					tagSpinner.stop().fadeOut("fast");
					createTagCloud(data);
				}
				if(settings.imageCloudAnchor) {
					imageSpinner.stop().fadeOut("fast");
					createImageCloud(data);
				}
			}
		});
	}

	function createTagCloud(data) {
		var tagCloud = $(settings.tagCloudAnchor);
		if(tagCloud.length > 0) {
			var tags = $("<ul/>")
				.css({
					listStyleType: "none",
					padding: 0
				})
				.appendTo(tagCloud);
			for(tagName in data) {
				var weight = data[tagName].weight + 1;
				var tag = $("<li>")
					.text(tagName)
					.css({
						fontSize: weight + "em",
						display: "inline-block",
						marginRight: ".25em"
					})
					.appendTo(tags);
			}
		}
		else {
			alert("Error: Could not find tagCloudAnchor with selector '" + settings.tagCloudAnchor + "'");
		}
	}

	function createImageCloud(data) {
		var imageCloud = $(settings.imageCloudAnchor).css({clear: "both", overflow: "auto"});
		if(imageCloud.length > 0) {
			for(tagName in data) {
				var imageWrapper = $("<div/>")
					.css({
						width: (data[tagName].weight + .5) * 10 + "em",
						height: (data[tagName].weight + .5) * 10 + "em",
						'float': "left",
						textAlign: "center",
						overflow: "hidden"
					})
					.appendTo(imageCloud)
					.image(data[tagName].url,
						{
							alt: tagName,
							title: tagName,
							css: "max-height:100%;display:none;"
						},
						function() {
							$(this).fadeIn("fast");
						}
					);
			}
		}
		else {
			alert("Error: Could not find imageCloudAnchor with selector '" + settings.imageCloudAnchor + "'");
		}
	}
}

$.fn.image=function(path, attr, callback){
	return this.each(function(){
		var image=new Image();
		image.onload=callback;
		image.src=path;
		image.title=attr.title;
		image.setAttribute("style", attr.css);
		image.alt=attr.alt
		this.appendChild(image);
	});
}
