Cms.InPlaceForm = Class.create({
	initialize: function(form, options) {
		this.form = $(form);
		
		// options
		this.prepareOptions();
		Object.extend(this.options, options || { });
		//this.form.title = this.options.clickToEditText;
		this.form.addClassName(this.options.formClassName);
		
		//this._originalBackground = this.form.getStyle('background-color') || 'transparent';

		this.registerListeners();
		this.createControls();
		
		this.form.getElements().each(function (element) {
			//id = element.id + '-static';
			element.hide();
		});
	},
	
	registerListeners: function() {
		this._listeners = { };
		var listener;
		$H(Cms.InPlaceForm.Listeners).each(function(pair) {
			listener = this[pair.value].bind(this);
			this._listeners[pair.key] = listener;
			this.form.observe(pair.key, listener);
		}.bind(this));
	},
		
	createControls: function () {
		//div = new Element('div');
		div = new Element('div', {'class': this.options.controlsDivClassName});
		div.appendChild(
			new Element('a', {'class': this.options.controlOkClassName})
				.update(this.options.controlOkText)
				.observe('click', this.handleFormSubmission.bind(this))
		);
		div.appendChild(
			new Element('a', {'class': this.options.controlCancelClassName})
				.update(this.options.controlCancelText)
				.observe('click', this.handleFormCancellation.bind(this))
		);
		div.hide()
		this.controlsDiv = div;
	},
	
	showForm: function () {
		this.form.getElements().each(function(input){
			element = $(input.id + '-static');
			element.hide();
			input.show();
			if ( input.hasClassName('tinymce') ) {
				//tinyMCE.execCommand('mceAddControl', false, input.id);
				input.startTinyMCE();
			}
		}.bind(this));
		// needed because of IE :\
		this.createControls();
		this.controlsDiv.show();
		this.form.appendChild(this.controlsDiv);
	},
	
	hideForm: function () {
		this.form.getElements().each(function(input){
			element = $(input.id + '-static');
			element.show();
			if ( input.hasClassName('tinymce') ) {
				//tinyMCE.execCommand('mceRemoveControl', false, input.id);
				input.stopTinyMCE();
			}
			input.hide();
		}.bind(this));
		this.controlsDiv.hide();
	}, 

	checkForEscapeOrReturn: function(e) {
		if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
		if (Event.KEY_ESC == e.keyCode)
			this.handleFormCancellation(e);
		else if (Event.KEY_RETURN == e.keyCode)
			this.handleFormSubmission(e);
	},

	destroy: function() {
		if (this._oldInnerHTML)
			this.element.innerHTML = this._oldInnerHTML;
		this.leaveEditMode();
		this.unregisterListeners();
	},
	
	enterEditMode: function(e) {
		if (this._saving || this._editing) return;
		this._editing = true;

		this.form.toggleClassName(this.options.formEditingClassName);
		//this.triggerCallback('onEnterEditMode');
		this.showForm();
		
		if (e) Event.stop(e);
	},
	
	leaveEditMode: function() {
		this.form.removeClassName(this.options.savingClassName);
		this.form.removeClassName(this.options.formEditingClassName);
		this.hideForm();
		this.leaveHover();
		this._saving = false;
		this._editing = false;
		this.triggerCallback('onLeaveEditMode');
	},

	enterHover: function(e) {
		if (this.options.hoverClassName)
			this.form.addClassName(this.options.hoverClassName);
		if (this._saving) return;
		this.triggerCallback('onEnterHover');
	},

	leaveHover: function(e) {
		if (this.options.hoverClassName)
			this.form.removeClassName(this.options.hoverClassName);
		if (this._saving) return;
		this.triggerCallback('onLeaveHover');
	},

	handleAJAXFailure: function(transport, ipe) {
    	this.form.innerHTML = transport.responseJSON.content;
    	this.errors = transport.responseJSON.errors;
    	
		//this.triggerCallback('onFailure', transport);
		//if (this._oldInnerHTML) {
		//	this.form.innerHTML = this._oldInnerHTML;
		//	this._oldInnerHTML = null;
		//}
	},
	
	handleAJAXComplete: function(transport, ipe) {
		this.leaveEditMode();
		//this.triggerCallback('onComplete', transport);
		this.initTinyMCE();
	},
	
	handleFormCancellation: function(e) {
		this.form.reset();
		this.leaveEditMode();
		//this.wrapUp();
		if (e) Event.stop(e);
	},
	
	// TODO
	handleFormSubmission: function(e) {
		this._saving = true;
		this.hideForm();
		this.leaveHover();
		this.showSaving();
		
		var params = this.form.serialize();
		//var params = this.options.callback(this.form, this.form) || '';
		if (Object.isString(params))
			params = params.toQueryParams();
		//params.editorId = this.element.id;
		if (this.options.htmlResponse) {
			var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
			Object.extend(options, {
				parameters: params,
				onComplete: this.handleAJAXComplete.bind(this),
				onFailure: this.handleAJAXFailure.bind(this)
			});
			new Ajax.Updater({ success: this.form }, this.form.action, options);
		} else {
			var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
			Object.extend(options, {
				parameters: params,
				onComplete: this.handleAJAXComplete.bind(this),
				onFailure: this.handleAJAXFailure.bind(this)
			});
			new Ajax.Request(this.url, options);
		}
		if (e) Event.stop(e);
	},
	
	prepareOptions: function() {
		this.options = Object.clone(Cms.InPlaceForm.DefaultOptions);
		Object.extend(this.options, Cms.InPlaceForm.DefaultCallbacks);
		[this._extraDefaultOptions].flatten().compact().each(function(defs) {
			Object.extend(this.options, defs);
		}.bind(this));
	},
	
	showSaving: function() {
		if ( this.options.savingText !== null ) {
			this._oldInnerHTML = this.form.innerHTML; 
			this.form.innerHTML = this.options.savingText;
		}
		this.form.addClassName(this.options.savingClassName);
		//this.form.style.backgroundColor = this._originalBackground;
		//this.form.show();
	},
	triggerCallback: function(cbName, arg) {
		if ('function' == typeof this.options[cbName]) {
			this.options[cbName](this, arg);
		}
	},
	unregisterListeners: function() {
		$H(this._listeners).each(function(pair) {
			if (!this.options.externalControlOnly)
				this.element.stopObserving(pair.key, pair.value);
			if (this.options.externalControl)
				this.options.externalControl.stopObserving(pair.key, pair.value);
		}.bind(this));
	},
	wrapUp: function(transport) {
		return;
		this.leaveEditMode();
		// Can't use triggerCallback due to backward compatibility: requires
		// binding + direct element
		this._boundComplete(transport, this.form);

		if (this.errors) {
			this.enterEditMode();
		   	$H(this.errors).each(function (p1) {
		   		msg = '';
		   		$H(p1.value).each(function (p2) {
		   			msg += p2.value + '<br />';
		   		}.bind(this));
	   			this.message(msg,$(this.elements.get(this.form.id + '-' + p1.key))); 
		   	}.bind(this));
		   	delete this.errrors;
		}

	},

	message: function (msg, element) {
		msgDiv1 = new Element('div', {id: 'inplaceform-message', style: 'xbackground: transparent url(\'../images/tooltip.gif\') no-repeat; padding: 16px 0 0 0; position: absolute;'});
		msgDiv2 = new Element('div', {style: 'color: #f55; font-weight: bold; border: 1px solid #fcc; background-color: #fff; padding: 10px 20px 5px 15px; position: relative;'});
		msgDiv2.update('<span style="font: normal 30px sans-serif; position: absolute; top: -20px; left: 0px;">&uarr;</span> ' + msg);
		msgDiv1.appendChild(msgDiv2);
		this.form.appendChild(msgDiv1);
		
		closeBtn = new Element('a', {style: 'cursor: pointer; text-decoration: none; position: absolute; top: 0px; right: 2px'});
		closeBtn.update('&times;');
		closeBtn.observe('click', function(){$('inplaceform-message').remove()});
		
		msgDiv2.appendChild(closeBtn);
		
		msgDiv1.clonePosition(element, {offsetTop: 10, offsetLeft: 0, setHeight: false});
	}

});

Object.extend(Cms.InPlaceForm, {
  DefaultOptions: {
    ajaxOptions: { },
    autoRows: 3,                                // Use when multi-line w/ rows == 1
    clickToEditText: 'Kliknij aby edytować',
    externalControl: null,                      // id|elt
    externalControlOnly: false,
    fieldPostCreation: 'activate',              // 'activate'|'focus'|false
    
    formClassName: 'inplaceform',
    formEditingClassName: 'editing',
    
    controlsDivClassName: 'inplaceform-controls',
    controlOkText: 'zapisz',
    controlCancelText: 'anuluj',
    controlOkClassName: 'inplaceform-controls-submit',
    controlCancelClassName: 'inplaceform-controls-cancel',
    
    formId: null,                               // id|elt
    highlightColor: '#f5f5ff',
    highlightEndColor: '#ffffff',
    hoverClassName: '',
    htmlResponse: true,
    loadingClassName: 'inplaceform-loading',
    loadingText: 'Loading...',
    paramName: 'value',
    rows: 1,                                    // If 1 and multi-line, uses autoRows
    savingClassName: 'cms-module-saving',
    savingText: null,
    size: 0,
    stripLoadedTextTags: false,
    submitOnBlur: false,
    textAfterControls: '',
    textBeforeControls: '',
    textBetweenControls: ''
  },
  DefaultCallbacks: {
    callback: function(form) {
      return Form.serialize(form);
    },
    onComplete: function(transport, element) {
      // For backward compatibility, this one is bound to the IPE, and passes
      // the element directly.  It was too often customized, so we don't break it.
      new Effect.Highlight(element, {
        startcolor: this.options.highlightColor, keepBackgroundImage: true });
    },
    onEnterEditMode: null,
    onEnterHover: function(ipe) {
      //ipe._originalBackground = ipe.form.style.backgroundColor; 
      ipe.form.style.backgroundColor = ipe.options.highlightColor;
      if (ipe._effect)
        ipe._effect.cancel();
    },
    //onFailure: function(transport, ipe) {
    //  alert('Error communication with the server: ' + transport.responseText.stripTags());
    //},
    onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
    onLeaveEditMode: null,
    onLeaveHover: function(ipe) {
      ipe._effect = new Effect.Highlight(ipe.form, {
        startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
        restorecolor: 'transparent', keepBackgroundImage: true
      });
    }
  },
  Listeners: {
    click: 'enterEditMode',
    keydown: 'checkForEscapeOrReturn',
    mouseover: 'enterHover',
    mouseout: 'leaveHover',
    submit: 'handleFormSubmission'
  }
});
