/**
 * Add validate handling for input elements.
 * 
 * The `.uiValidate()` method add validate handling to a input elements.
 * 
 * The `.uiValidate()` method is using the ep.validate module for validation, all available types of
 * ep.validate[ type ] are supported. Have a look at the additional options, some option are only available for
 * special validation types.
 * 
 * ### Examples
 * Apply .uiValidate() to input element named email.
 * 
 * JavaScript:
 * 
 *     ep(':input[name=email]')
 *         .uiValidate({
 *             required:   true,
 *             type:       'email'
 *         });
 * 
 * HTML:
 * 
 *     <form>
 *       <input type="text" name="email" />
 *     </form>
 * 
 * 
 * @class jQuery.ui.uiValidate
 * @extends jQuery.ui.uiInput
 * 
 * @uses ep.validate
 * @uses ep.ui.input
 * @since 6.11.0
 */

/**
 * @cfg {String} type An available validation type from ep.validate[ type ].
 */

/**
 * @cfg {Boolean} valid A boolean indication wether the input is valid on startup.
 */

/**
 * @cfg {Boolean} required A boolean indication wether the value is required.
 */

/**
 * @cfg {Integer} min A minimum valid number.
 */

/**
 * @cfg {Integer} max A maximum valid number.
 */

/**
 * @cfg {Integer} minlength A minimum number of chars.
 */

/**
 * @cfg {Integer} maxlength A maximum number of chars.
 */

/**
 * @cfg {String} format A date/number formatter [look at the jQuery.i18n plugin].
 */

/**
 * @cfg {String} region An i18n region [look at the jQuery.i18n plugin].
 */

/**
 * @cfg {Boolean} strict A boolean indication wether to validate in strict mode.
 */

/**
 * @cfg {String} accept A list of accepted mimetypes or mimetype groups.
 */

/**
 * See `jQuery.ui.uiValidate` for details.
 * 
 * @param {Object} [options] A map of additional options pass to the method.
 * @param {String} type An available validation type from ep.validate[ type ].
 * @param {Boolean} valid A boolean indication wether the input is valid on startup.
 * @param {Boolean} required A boolean indication wether the value is required.
 * @param {Integer} min A minimum valid number.
 * @param {Integer} max A maximum valid number.
 * @param {Integer} minlength A minimum number of chars.
 * @param {Integer} maxlength A maximum number of chars.
 * @param {String} format A date/number formatter [look at the jQuery.i18n plugin].
 * @param {String} region An i18n region [look at the jQuery.i18n plugin].
 * @param {Boolean} strict A boolean indication wether to validate in strict mode.
 * @param {String} accept A list of accepted mimetypes or mimetype groups.
 * 
 * @method uiValidate
 * @member jQuery
 * 
 * @since 6.11.0
 */

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


define("ep/ui/validate", [
	"jquery",
	"ep",

	"ep/dict", // Extends prototype methods of $.dict (translateData)
	"ep/validate",
	"ep/ui/input"
], function ($, ep) {

	// formular felder
	$.widget('ui.uiValidate',$.ui.uiInput,{

		options: {
	// ep.ui.Input
		//	big:				true,
		//	autofocus:			false,
		//	placeholder:		'text',
		//	info:				'text',

	// ep.ui.Validate
		//	accept:				'',
		//	min:				1,
		//	max:				20,
		//	minlength:			1,
		//	maxlength:			4,
		//	pattern:			[\w]+,
		//	required:			true,
		//	format:				'n0',
		//	currency:			'EUR',
			valid:				true,
			type:				'basic',
			showError:          true
		},

		_create: function(){
			this._superApply(arguments);

			this.options = $.extend({
					accept:		this.elem.attr('accept'),
					min:			parseInt( this.elem.attr('min'), 10 ),
					max:			parseInt( this.elem.attr('max'), 10 ),
					minlength:		parseInt( this.elem.attr('minlength'), 10 ),
					maxlength:		parseInt( this.elem.attr('maxlength'), 10 ),
					pattern:		this.elem.attr('pattern'),
					required:		this.elem.attr('required')
				},this.options);

			// make .uiValidate as .uiInput also available to fix addClass for type radio
			this.elem
				.addClass('ep-uiValidate')
				.on( 'validate.uiValidate blur.uiValidate', $.proxy(this, '_validate') );

			// validate if invalid on default
			if( !this.options.valid ){
				this._setInstantly();
				this._setValidStatus(false);
			}

		},

		_init: function(){
			// init uiInput
			this._superApply(arguments);
		},

		_setInstantly: function(){
			this._instantly = true;
			this.elem.on( 'changeValue.uiValidate', $.proxy(this, '_validate') );
		},

		_radioGroupCheck: function(){
			this.elem
				.formGroup(':radio')
				.trigger('validate');
		},

		_changeAttr: function( event, attr ){
			var self = this;

			this._superApply(arguments);

			$.each( attr, function( name, value ){
				if( (/^(accept|pattern|required)$/i).test(name) ){
					self.options[ name ] = value;
				}
				else if( (/^(min|max|minlength|maxlength)$/i).test(name) ){
					self.options[ name ] = parseInt( value, 10 );
				}
			});
		},

		_setOption: function( name, value ){
			if( name=='valid' && value!==undefined ){
				this._setValidStatus(value);
			}
			return this._superApply(arguments);
		},

		_setValidStatus: function( valid ){
			this.valid = valid===false ? ep.validate.basic("") : valid;
			valid = valid!==true;
			this.elem[0].formInvalid = valid;
			if( this.placeholder ){
				this.placeholder[0].formInvalid = valid;
			}
			if(this.options.showError) {
			    this.elem.toggleClass('ui-invalid', valid);
			    this._tooltipShow();
			}
		},

		_validate: function( event ){
			if( event.keyCode!==9 ){

				var val = this.elem.val(),
					valid;

				if( this.elem.is(':radio') ){
					val = this.elem
						.formGroup(':radio')
						.filter(':checked')
						.val() || '';
				}
				else if( this.elem.is(':checkbox') ){
					val = this.elem
						.filter(':checked')
						.val() || '';
				}

				valid = ep.validate[ this.options.type ]( val, this.options );

				if( valid!==true && !this._instantly ){
					this._setInstantly();
				}

				this._setValidStatus(valid);

				if( event.type!=='changeAttr' ){
					$(this.elem[0].form).trigger('change');
				}
			}
		},

		_createErrorMsgOptions: function(){
			// options for errer msg
			var options = {
					min: this.options.min,
					max: this.options.max,
					minlength: this.options.minlength,
					maxlength: this.options.maxlength
				},
				format = this.options.format,
				opts = {region:this.options.region};

			// i18n for min + max
			if( this.options.type === 'number' ){
				opts.currency = this.options.currency;

				options.example = $.i18n.formatNumber( 21.45923, format, opts );

				if( options.min || options.max ){
					options.min = $.i18n.formatNumber( options.min, format, opts );
					options.max = $.i18n.formatNumber( options.max, format, opts );
				}
			}
			else if( this.options.type === 'date' ){
				options.example = $.i18n.formatDate( new Date(), format, opts );

				if( options.min || options.max ){
					options.min = $.i18n.formatDate( new Date(options.min), format, opts );
					options.max = $.i18n.formatDate( new Date(options.max), format, opts );
				}
			}
			return options;
		},

		_tooltipShow: function(){
			if( this.valid!==true ){
				// create tooltip if not exists
				if( !this.tooltip ){
					this._tooltipInit(true);
					this.tooltip.on( 'show', $.proxy(this, '_tooltipHide') );
				}
				if( !this.errormsg ){
					this.errormsg = $('<div>')
						.addClass('ep-uiValidate-message')
						.insertBefore(this.tooltip);
					this.stack.push(this.errormsg[0]);
				}
				// options for errer msg
				var options = this._createErrorMsgOptions();

				// set tooltip msg
				this.errormsg.text( this.dict.translateData( this.valid, options ) );
				this.errormsg.show();

				if( this.elem.is(':focus') ){
					this.tooltip.uiTooltip('show');
				}
			}
			else{
				this._tooltipHide();
			}
		},

		_tooltipHide: function(){
			var self = this,
				hidemsg = function(){
					if( self.errormsg ){
						self.errormsg.hide();
					}
				};

			if( this.tooltip && this.valid===true ){
				if( !this.options.info ){
					this.tooltip.uiTooltip('hide',hidemsg);
				}
				else{
					hidemsg();
				}
			}
		},

		destroy: function(){
			this.elem
				.off('.uiValidate')
				.removeClass(/ep-uiValidate[\w\d-]*/g);

			this._superApply(arguments);
		}
	});

	return ep;

});