jQuery.fn.jipe = function(options) {

	// private properties
	// ==================
	var options = $.extend({
		contentSelector : "jipe-content",
		parametersSelecter : "jipe-parameters",
		editorOptionsSelector : "jipe-editor-options",		
		updateHandlerSelector : "jipe-update-handler",
		openFunction : null,
		closeFunction : null,
		buttonHolderSelector : "jipe-button-holder",
		cancelButtonSelector : "jipe-cancel-button",
		cancelButtonText : "cancel",
		updateButtonSelector : "jipe-update-button",
		updateButtonText : "update",
		updateErrorText : "Error: the content could not be updated, contact your administrator if the error keeps occurring."
	}, options);


	// private methods
	// ===============	
	var generateJipe = function(jipe) {	
		// define jipe update handler and parameters
		var updateHandler = $(jipe).find("." + options.updateHandlerSelector);
		
		var parameters = {};
		var parametersContainer = $(jipe).find("." + options.parametersSelecter);			
		if (parametersContainer) {
			for (var j = 0; j < parametersContainer[0].children.length; j++) {
				var name = parametersContainer[0].children[j].className;
				var value = parametersContainer[0].children[j].value;			
				parameters[name] = value;
			}
		}
		
		var editorOptions = {};
		var editorOptionsContainer = $(jipe).find("." + options.editorOptionsSelector);
		for (var k = 0; k < editorOptionsContainer[0].children.length; k++) {
			var name = editorOptionsContainer[0].children[k].className;
			var value = editorOptionsContainer[0].children[k].value;			
			editorOptions[name] = value;
		}
		
		// create jipe object
		var jipe = {
			updateHandler : updateHandler[0].value,
			editorOptions : editorOptions,
			parameters : parameters,
			element : jipe,
			created : false
		};
		
		// remove jipe updateHandler & parameters fields
		$(updateHandler[0]).remove();
		if (parametersContainer) {
			$(parametersContainer[0]).remove();
		}
		$(editorOptionsContainer[0]).remove();
		
		$(jipe.element).dblclick(function() {
			openJipe(jipe);
		});

		//jipes.push(jipe);
	}
	var openJipe = function(jipe) {
		if (options.openFunction != null) {
			options.openFunction();
		}
		if (!jipe.created) {
			jipe.element.buttonHolder = document.createElement("DIV");
			jipe.element.buttonHolder.className = options.buttonHolderSelector;

			var cancelButton = document.createElement("INPUT");
			cancelButton.type = "submit";
			cancelButton.value = options.cancelButtonText;
			cancelButton.className = options.cancelButtonSelector;
			$(cancelButton).click(function() {
				closeJipe(jipe);				
				return false;
			});
			$(jipe.element.buttonHolder).append(cancelButton);
			
			var updateButton = document.createElement("INPUT");
			updateButton.type = "submit";
			updateButton.value = options.updateButtonText;
			updateButton.className = options.updateButtonSelector;
			$(updateButton).click(function() {
				updateContent(jipe);
				return false;
			});
			$(jipe.element.buttonHolder).append(updateButton);
			
			jipe.created = true;
		}
		
		$(jipe.element).after(jipe.element.buttonHolder);
		jipe.editor = CKEDITOR.replace(jipe.element, jipe.editorOptions);		
	}
	var closeJipe = function(jipe) {
		$(jipe.element.buttonHolder).detach();
		jipe.editor.destroy();
		if (options.closeFunction != null) {
			options.closeFunction();
		}
	}
	var updateContent = function(jipe) {
		var updateParameters = jipe.parameters;
		updateParameters.data = jipe.editor.getData();
		$.ajax({
			type : "POST",
			url : jipe.updateHandler,
			data : jipe.parameters,
			success : function(msg)	{
				if (msg == "true") {
					closeJipe(jipe);
					
				} else {
					alert(options.updateErrorText);
				}
			},
			error : function (XMLHttpRequest, textStatus, errorThrown) {
				alert(options.updateErrorText);
			}
		});
	}
	
	
	// public methods
	// ==============
	this.each(function() {
		//editableContent =  $(this).find("." + options.contentSelector);
		generateJipe(this);
	});	
	
	return this;
}


