(function($) {
		  
	$.fn.recaptcha = function(opts) {

		if (this.length > 1){
			this.each(function() { $(this).recaptcha(opts) });
			return this;
		}

		/* options */
		var defaults = {
			captcha_url	  	: "https://api-secure.recaptcha.net/image?c=",
			challenge_url	: "/ajax/recaptcha.php",
			challenge	  	: "",
			
			image_id		: "recaptcha_image",
			reload_id 		: "recaptcha_reload",
			challenge_id 	: "recaptcha_challenge",
			answer_id		: "recaptcha_answer"
		};
		
		var options = $.extend({}, defaults, opts);

		var object = this;
		
		/* gets a new challenge string */
		this.getChallenge = function (callback) {
			$.get(options.challenge_url, '', function (data) {
				options.challenge = data.challenge;

				if ($.isFunction(callback)) callback();
				
			}, 'json');
		};
		
		/* updates the captcha with a new image */
		this.reloadCaptcha = function (node) {
			$(node).addClass('loading');
			
			object.getChallenge(function () {

				/* update image */
				$('#' + options.image_id).attr('src', options.captcha_url + options.challenge);
				
				/* save new challenge */
				$('#' + options.challenge_id).val(options.challenge);
				
				/* clear text field */
				$('#' + options.answer_id).val('');
				
			});
		};
		
		/* private functions */
		
		var initialize = function (node) {
			
			$(node).addClass('loading');
			$(node).text('');

				
			/* add hidden field for challenge, answer field & refresh button */
			$('<input type="hidden" name="'+options.challenge_id+'" id="'+options.challenge_id+'"  /> \
			   <input type="text" class="input_text required" name="'+options.answer_id+'" id="'+options.answer_id+'" /> \
			   <a href="#" id="'+options.reload_id+'" title="Get new words"></a>').insertAfter($(node));


			object.getChallenge(function () {
				
				/* add captcha image */
				$('<img src="' + options.captcha_url + options.challenge + '" alt="" id="'+options.image_id+'" />').prependTo($(node));
				
				/* show the image each time it finishes loading */
				$('#' + options.image_id).bind('load', function () {
					$(node).removeClass('loading');									  
				});
				
				/* save challenge */
				$('#' + options.challenge_id).val(options.challenge);
				
			});
			
			/* add event to reload button */
			$('#' + options.reload_id).live('click', function () {
				object.reloadCaptcha($(node));
				return false;
			});

		};

		return initialize(this);
	};


})(jQuery);