/**
 * Make a text editable.
 *
 * The `.uiTextedit()` method make an element editable on click the element.
 *
 * ### Examples
 * Make all divs with class edit editable and strip HTML tags on edit.
 *
 * JavaScript:
 *
 *     ep('div.edit')
 *         .uiTextedit({
 *             stripHTML: true
 *         });
 *
 *
 * @class jQuery.ui.uiTextedit
 * @extends jQuery.widget
 *
 * @uses ep
 * @uses ep.ajax
 * @uses ep.ui.input
 * @uses jQuery.ui.core
 * @since 6.11.0
 */

/**
 * @event onBeforeOpen This event is triggered before the editable element is displayed.
 * @member jQuery.ui.uiTextedit
 * @since 6.12.0
 */

/**
 * @event onAfterOpen This event is triggered when the editable element is displayed.
 * @member jQuery.ui.uiTextedit
 * @since 6.12.0
 */

/**
 * @event onAfterClose This event is triggered when the data was written back and the editable element is closed.
 * @member jQuery.ui.uiTextedit
 * @since 6.12.0
 */

/**
 * @event formatOnWriteBack This event is triggered before datas write back an before the editable element will be hidden.
 * @member jQuery.ui.uiTextedit
 * @since 6.12.0
 */

/**
 * Show the text input.
 *
 * @method open
 * @member jQuery.ui.uiTextedit
 *
 * @since 6.15.1
 */

/**
 * @cfg {String} type A input type such as 'input' or 'textarea'.
 */

/**
 * @cfg {String} action A url as for save action.
 */

/**
 * @cfg {String} action An ObjectID for save action.
 */

/**
 * @cfg {String} name A name for the value to save.
 */

/**
 * @cfg {Boolean} convertLineBreaks A boolean indication whether to convert line breaks to <br /> tags.
 */

/**
 * @cfg {Boolean} stripHTML A boolean indication whether to remove HTML tags from the text.
 */

/**
 * @cfg {undefined} validate An object contenting validation options (available options see ep.uiValidate)
 */

/**
 * @cfg {undefined} additional An object contenting additional parameters (key/value pairs) for the ajax-request
 */

/**
 * @cfg {undefined} rows Number of displayed rows of a textarea.
 */

/**
 * @cfg {undefined} width Width of the input or textarea.
 */

/**
 * See `jQuery.ui.uiTextedit` for details.
 *
 * @param {Object} [options] A map of additional options pass to the method.
 * @param {String} type A input type such as 'input' or 'textarea'.
 * @param {String} action A url as for save action.
 * @param {String} action An ObjectID for save action.
 * @param {String} name A name for the value to save.
 * @param {Boolean} convertLineBreaks A boolean indication whether to convert line breaks to <br /> tags.
 * @param {Boolean} stripHTML A boolean indication whether to remove HTML tags from the text.
 * @param {undefined} validate An object contenting validation options (available options see ep.uiValidate)
 * @param {undefined} additional An object contenting additional parameters (key/value pairs) for the ajax-request
 * @param {undefined} rows Number of displayed rows of a textarea.
 * @param {undefined} width Width of the input or textarea.
 *
 * @fires onBeforeOpen
 * @fires onAfterOpen
 * @fires onAfterClose
 * @fires formatOnWriteBack
 *
 * @method uiTextedit
 * @member jQuery
 *
 * @since 6.11.0
 */

/*
 * @copyright		© Copyright 2006-2010, epages GmbH, All Rights Reserved.
 *
 * @module			ep.ui.textedit
 */

define("ep/ui/textedit", [
	"jquery",
	"ep",
	"util/string",

	"jquery/ui/core",
	"ep/ajax",
	"ep/ui/input"
], function ($, ep, str) {

	$.widget( "ui.uiTextedit",/* my.parent.widget,*/ {
		MIN_WIDTH: 50,
		options: {
		//	validate: 			undefined,
			additional:			undefined,												// additional save parameters (e.g. CurrencyID)
			type:				'input',												// textarea or input
			rows:               undefined,												// number of rows which should be displayed in a textarea
			width:              undefined,                                              // width of the input or textarea
			action:				null,													// save action
			objectId:			ep.config.objectId !== 0 ? ep.config.objectId : null,	// object id for save
			name:				null,													// name for save
			convertLineBreaks:	false,													// new line to br
			stripHTML:			false,													// remove html tags
			xhrType:			'POST',													// request type
			onAfterClose:		null,
			onBeforeOpen:		null,
			onAfterOpen:		null,
			formatOnWriteBack:	null,
			preventDefaultOnEnter : false // Call *preventDefault()* on event *keypress* with key 'ENTER';
		},

		_create: function(){
			var o = this.options;

			this.elem = this.element;

			this.elem
				.on('click.uiTextedit', $.proxy(this, '_open'));
				/*.on( 'mouseover.uiTextedit', $.proxy(this, '_onmouseover') )
				.on( 'mouseout.uiTextedit', $.proxy(this, '_onmouseout') );*/
		},

		_build: function(){
			var self = this,
				o = self.options;

			this.elem
				.on( 'mouseover.uiTextedit', $.proxy(this, '_onmouseover') )
				.on( 'mouseout.uiTextedit', $.proxy(this, '_onmouseout') );

			this.uiInput = ep( o.type === 'textarea' ? '<textarea>' : '<input type="text">' )
				.hide()
				.insertAfter( this.elem );
			if( o.type === 'textarea' && o.rows ){
				this.uiInput.attr('rows', o.rows);
			}
			if(o.validate){
				this.uiInput.uiValidate(o.validate);
			}else{
				this.uiInput.uiInput();
			}
			this.uiInput
				//.uiInput()
				.uiInput('addClass', 'ep-uiTextedit-wrap')
				.on( 'blur.uiTextedit', $.proxy(this, '_close') )
				.on( 'keypress.uiTextedit', $.proxy(this, '_onkeypress') )
				.on( 'keyup.uiTextedit', $.proxy(this, '_onkeyup') );

			//if we have a action we also need a name to save content to the server
			if( o.action ){
				if( o.name || name ){
					this._name = o.name || name;
				}
				else{
					this._name = this.elem.attr('name');
					if( !this._name ){
						console.warn('ep.ui.textedit: unable to save: action is defined but no name is defined');
					}
				}
			}
		},

		_open:function( event ){
			// build textedit construct if necessary
			if(this.uiInput === undefined){
				this._build();
			}

			if((this.options.onBeforeOpen!=null) && (typeof this.options.onBeforeOpen=="function")){
				this.options.onBeforeOpen(this.uiInput);
			}

			this.content = this.elem.html();
			var content = this.content;

			this.uiInput.width( this.options.width || Math.max( this.elem.width(), this.MIN_WIDTH ) );
			this.elem.hide();

			this.uiInput
				.show()
				.css( 'display', (this.elem.data("olddisplay") !== undefined) ? this.elem.data("olddisplay") : 'inline-block' );

			if( this.options.convertLineBreaks ){
				content = content.replace(/(<br>|<br \/>)/g, '\n');
			}

			this.uiInput
				.attr({
					//'disabled': false,
					'value': content
				})
				.focus()
				.select();

			if((this.options.onAfterOpen!=null) && (typeof this.options.onAfterOpen=="function")){
				this.options.onAfterOpen(this.uiInput);
			}
		},

		_close:function(evt){
			var o = this.options;

			if(!this.uiInput.is(':disabled[disabled]') && !this.uiInput.is(':hidden')) {
			// Otherwise *_close()* has already been called by *_onkeypress()* ('Enter') or
			// *_writeContentBack()* was called by *_onkeyup* ('ESC').
				if(this.uiInput.is(':input:invalid')){
					evt.preventDefault();
					//this.uiInput.focus();
					return;
				}

				this._writeContentBack(evt);
				if (o.action && o.objectId && this._name) {
					this._saveContent();
				}
				//this.uiInput.attr('disabled', true);

				if((this.options.onAfterClose != null) && (typeof this.options.onAfterClose == "function")){
					this.options.onAfterClose(this.uiInput);
				}
			}
		},

		_onkeypress: function( event ){
			/*if( event.keyCode === 27 ){
				this.uiInput.val(this.content);
				this._writeContentBack(event);
			}*/
			var o = this.options;
			if( o.type === 'input' && event.keyCode === 13 ){
				if (o.preventDefaultOnEnter) {
					event.preventDefault();
				}
				this._close(event);
			}
		},

		_onkeyup: function( event ){
			if( event.keyCode === 27 ){
				this.uiInput.val(this.content);
				this._writeContentBack(event);
			}
		},

		_onmouseover: function(){
			this.elem.addClass('ep-uiTextedit-Hover');
		},

		_onmouseout: function(){
			this.elem.removeClass('ep-uiTextedit-Hover');
		},

		_writeContentBack: function(event){
			var o = this.options;

			this.elem.show();
			this.uiInput.hide();

			// FIRST
			if((o.formatOnWriteBack!=null) &&(typeof o.formatOnWriteBack=="function")){
				o.formatOnWriteBack(this.uiInput, event);
			}

			this.content = this.uiInput.val();
			if( o.stripHTML){
				this.content = str.stripTags(this.content);
			}
			if( o.convertLineBreaks){
				this.content = this.content.replace( /(\n)/g, '<br />' );
			}
			/*if((o.formatOnWriteBack!=null) &&(typeof o.formatOnWriteBack=="function")){
				o.formatOnWriteBack(this.uiInput, event);
			}*/
			this.elem.html(this.content);
		},

		_saveContent: function(){
			var o = this.options,
				jsonData = {
					'ViewAction':	'JSONViewResponse',
					'ObjectID':		o.objectId,
					'ChangeAction':	o.action
				};

			jsonData[this._name] = this.content;
			// add additional parameters (e.g. CurrencyID)
			if(o.additional!==undefined){
				$.extend(jsonData, o.additional);
			}

			ep.ajax({
				dataType:	'json',
				data:		jsonData,
				type:		o.xhrType,
				context:	this
			});
		},

		open: function(){
			if(!this.uiInput || (this.uiInput && !this.uiInput.is(':visible'))){
				this._open();
			}
		},

		destroy: function(){
			if(this.uiInput){
				this.uiInput.remove();
			}

			this.elem
				.off('.uiTextedit')
				.show();

			this._superApply(arguments);
		}

	});

	return ep;

});