/**
 * @class ep.validate
 *
 */

/*
 * @copyright		© Copyright 2006-2010, epages GmbH, All Rights Reserved.
 *
 * @module			ep.validate
 *
 * @revision		$Revision: 1.9 $
 */

define("ep/validate", [
	"jquery",
	"ep",
	"util/mime",

	"ep/color",
	"ep/i18n"
], function ($, ep, mime) {

/*
 * @dictionary			ep.dict
 *
 * @translation			{NOT_VALID}
 *						{REQUIRED}
 *						{NOT_IN_RANGELENGTH}
 *						{LOWER_THAN_MINLENGTH}
 *						{GREATER_THAN_MAXLENGTH}
 *						{NOT_IN_RANGE}
 *						{LOWER_THAN_MIN}
 *						{GREATER_THAN_MAX}
 *						{NO_EMAIL}
 *						{NO_URL}
 *						{NO_MIME}
 *						{MIME_NOT_ACCEPT}
 *						{NO_CREDITCARD_NUMBER}
 *						{NO_NUMBER}
 *						{NO_CURRENCY}
 *						{NO_PERCENT}
 *						{NO_DATE}
 *						{NO_DATETIME}
 *						{NO_TIME}
 *						{NO_COLOR_VALUE}
 *						{NO_UNIT}
 *						{NO_UNIT_VALUE}
 *						{NO_CSS_NUMBER}
 *						{FLOAT_NOT_ALLOWED}
 *						{UNKOWN_UNIT}
 *						{NO_ENTRY_SELECTED}
 */

	var invalid = 'NOT_VALID',

		isN = function( value ){
			return !isNaN(value);
		},

		pattern = function( value, pattern ) {
			return pattern ? ( new RegExp( ((/^\^/).test(pattern)?'':'^') + pattern + ((/\$$/).test(pattern)?'':'$') , '' ).test( value ) || invalid ) : true;
		},

		required = function( value, req ) {
			return !value && req ? 'REQUIRED' : true;
		},

		rangelength = function( value, min, max ) {
			min = min<0 ? 0 : min;
			max = max<0 ? 0 : max;

			var val = $.trim(value).length;

			if( isN(min) && min>val ){
				return isN(max) ? 'NOT_IN_RANGELENGTH' : 'LOWER_THAN_MINLENGTH';
			}
			if( isN(max) && val>max ){
				return isN(min) ? 'NOT_IN_RANGELENGTH' : 'GREATER_THAN_MAXLENGTH';
			}
			return true;
		},

		range = function( value, min, max ) {
			var val = typeof value !== 'number' ? parseFloat(value,10) : value;

			if( isN(min) && min>val ){
				return isN(max) ? 'NOT_IN_RANGE' : 'LOWER_THAN_MIN';
			}
			if( isN(max) && val>max ){
				return isN(min) ? 'NOT_IN_RANGE' : 'GREATER_THAN_MAX';
			}
			return true;
		},

		i18nMap = {
			'date':					'd',
			'dateLong':				'D',
			'dateLong-time':		'f',
			'dateLong-timeLong':	'F',
			'date-time':			'l',
			'date-timeLong':		'L',
			'time':					't',
			'timeLong':				'T',
			'currency':				'c',
			'number':				'n',
			'percent':				'p'
		};

	$.extend( $.scope('ep.validate'), {

		/**
		 * Validate a email address.
		 *
		 * The `ep.validate.email()` method checks if the givn string an valid email address.
		 *
		 * ### Examples
		 * Validate an email address.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.email( 'mmustermann@epages.com' );
		 *
		 * Results:
		 *
		 *     true
		 *
		 * Validate an email address with error return.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.email( 'mmustermann@epages' );
		 *
		 * Results:
		 *
		 *     NO_EMAIL
		 *
		 *
		 * ### Dependencies
		 *
		 *  + `ep`
		 *  + `ep.color`
		 *  + `jQuery.mime`
		 *  + `jQuery.i18n`
		 *
		 * @param {String} value A text to validate
		 * @param {Object} [options] A map of additional options pass to the method.
		 * @param {Boolean} options.required A boolean indication wether the value is required.
		 * @param {Integer} options.minlength A minimum number of chars.
		 * @param {Integer} options.maxlength A maximum number of chars.
		 *
		 * @method email
		 * @static
		 * @member ep.validate
		 *
		 * @since 6.11.0
		 */
		email: function( value, options ){
			value = $.trim(value);

			var opt = $.extend({},options||{}),
				valid = required( value, opt.required );

			if( value && valid===true ){
				valid = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value) || 'NO_EMAIL';
				// EPG-24121: check the local part of an email address for non-ASCII characters
				if( valid===true ){
					var localatoms = value.split('@')[0].split('.');
					$.each(localatoms, function(index) {
						valid = /^[\x00-\x7F]+$/.test(localatoms[index]) || 'NO_EMAIL';
						return valid=='NO_EMAIL' ? false : true;
					});
				}
			}
			return valid===true ? range( value, opt.minlength, opt.maxlength ) : valid;
		},
		// url must be absolute
		/**
		 * Validate a url.
		 *
		 * The `ep.validate.url()` method checks if the givn string an valid url.
		 *
		 * ### Examples
		 * Validate an url.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.email( 'http://www.epages.com' )
		 *
		 * Results:
		 *
		 *     true
		 *
		 * Validate an url with error return.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.email( 'epages' );
		 *
		 * Results:
		 *
		 *     NO_URL
		 *
		 *
		 * ### Dependencies
		 *
		 *  + `ep`
		 *  + `ep.color`
		 *  + `jQuery.mime`
		 *  + `jQuery.i18n`
		 *
		 * @param {String} value A text to validate
		 * @param {Object} [options] A map of additional options pass to the method.
		 * @param {Boolean} options.required A boolean indication wether the value is required.
		 * @param {Integer} options.minlength A minimum number of chars.
		 * @param {Integer} options.maxlength A maximum number of chars.
		 *
		 * @method url
		 * @static
		 * @member ep.validate
		 *
		 * @since 6.11.0
		 */
		url: function( value, options ){
			value = $.trim(value);

			var opt = $.extend({},options||{}),
				valid = required( value, opt.required );

			if( value && valid===true ){
				valid = /^((https?|ftp):\/\/)?(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value) || 'NO_URL';
			}
			return valid===true ? range( value, opt.minlength, opt.maxlength ) : valid;
		},

		/**
		 * Validate a mimetype.
		 *
		 * The `ep.validate.mimetype()` method checks if the givn string an valid mimetype and optional an accepted mimetype.
		 *
		 * ### Examples
		 * Validate a mimetype.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.mimetype( 'image/jpeg' )
		 *
		 * Results:
		 *
		 *     true
		 *
		 * Validate a mimetype with error return.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.mimetype( 'img' );
		 *
		 * Results:
		 *
		 *     NO_MIME
		 *
		 * Validate an mimetype with accept option.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.mimetype( 'image/jpeg', {accept:'text/*'} );
		 *
		 * Results:
		 *
		 *     MIME_NOT_ACCEPT
		 *
		 *
		 * ### Dependencies
		 *
		 *  + `ep`
		 *  + `ep.color`
		 *  + `jQuery.mime`
		 *  + `jQuery.i18n`
		 *
		 * @param {String} value A text to validate
		 * @param {Object} [options] A map of additional options pass to the method.
		 * @param {Boolean} options.required A boolean indication wether the value is required.
		 * @param {String} options.accept A list of accepted mimetypes or mimetype groups.
		 *
		 * @method mimetype
		 * @static
		 * @member ep.validate
		 *
		 * @since 6.11.0
		 */
		mimetype: function( value, options ){
			value = $.trim(value);

			var opt = $.extend({
					accept: undefined
				},options||{}),
				valid = required( value, opt.required );

			if( value && valid===true ){
				valid = /^[a-z]+\/[a-z\d\.-]+$/i.test(value) || 'NO_MIME';
			}
			if( value && opt.accept && valid===true ){
				valid = mime.mime( value, opt.accept ) || 'MIME_NOT_ACCEPT';
			}
			return valid;
		},

		/**
		 * Validate a creditcard number.
		 *
		 * The `ep.validate.creditcard()` method checks if the givn string an valid creditcard number.
		 *
		 * ### Examples
		 * Validate a creditcard number.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.creditcard( '4111111111111111' )
		 *
		 * Results:
		 *
		 *     true
		 *
		 * Validate a creditcard with error return.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.creditcard( '4112334589700711' );
		 *
		 * Results:
		 *
		 *     NO_CREDITCARD_NUMBER
		 *
		 *
		 * ### Dependencies
		 *
		 *  + `ep`
		 *  + `ep.color`
		 *  + `jQuery.mime`
		 *  + `jQuery.i18n`
		 *
		 * @param {String} value A text to validate
		 * @param {Object} [options] A map of additional options pass to the method.
		 * @param {Boolean} options.required A boolean indication wether the value is required.
		 *
		 * @method creditcard
		 * @static
		 * @member ep.validate
		 *
		 * @since 6.11.0
		 */
		creditcard: function( value, options ) {
			value = $.trim(value);

			var opt = $.extend({},options||{}),
				valid = required( value, opt.required );

			if( value && valid===true ){
				if( /[^0-9-]+/.test(value) ){
					return false;
				}

				var nCheck = 0,
					nDigit = 0,
					bEven = false,
					cDigit;

				value = value.replace(/\D/g, "");

				for( var n=value.length-1 ; n>=0 ; n-- ){
					cDigit = value.charAt(n);
					nDigit = parseInt(cDigit, 10);
					if( bEven ){
						if( (nDigit *= 2) > 9 ){
							nDigit -= 9;
						}
					}
					nCheck += nDigit;
					bEven = !bEven;
				}

				valid = (nCheck % 10) === 0 || 'NO_CREDITCARD_NUMBER';
			}
			return valid;
		},

		/**
		 * Validate a date.
		 *
		 * The `ep.validate.date()` method checks if the givn string an valid date.
		 *
		 * ### Examples
		 * Validate a date.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.date( '01.02.2011', {format: 'd', region: 'de'} );
		 *
		 * Results:
		 *
		 *     true
		 *
		 * Validate a date with error return.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.date( '01/02/2011', {format: 'd', region: 'de'} );
		 *
		 * Results:
		 *
		 *     NO_DATE
		 *
		 *
		 * ### Dependencies
		 *
		 *  + `ep`
		 *  + `ep.color`
		 *  + `jQuery.mime`
		 *  + `jQuery.i18n`
		 *
		 * @param {String} value A text to validate
		 * @param {Object} [options] A map of additional options pass to the method.
		 * @param {Boolean} options.required A boolean indication wether the value is required.
		 * @param {String} options.format A date formatter [look at jQuery.i18n plugin].
		 * @param {String} options.region An i18n region [look at jQuery.i18n plugin].
		 * @param {Boolean} options.strict A boolean indication wether to validate in strict mode.
		 * @param {Integer} options.min A local timestamp (not UTC) as minimum valid date.
		 * @param {Integer} options.max A local timestamp (not UTC) as maximum valid date.
		 *
		 * @method date
		 * @static
		 * @member ep.validate
		 *
		 * @since 6.11.0
		 */
		date: function( value, options ){
			value = $.trim(value);

			var opt = $.extend({
					format: 'd',
					strict: false
				},options||{}),
				region = {region:opt.region},
				valid = required( value, opt.required );

			opt.format = i18nMap[opt.format] || opt.format;

			if( value && valid===true ){
				switch(true){
					case (/^(d|D)$/).test(opt.format):
						valid = 'NO_DATE';
					break;
					case (/^(f|F|l|L)$/).test(opt.format):
						valid = 'NO_DATETIME';
					break;
					case (/^(t|T)$/).test(opt.format):
						valid = 'NO_TIME';
					break;
					default:
						valid = invalid;
					break;
				}
				valid = new RegExp( '^' + $.i18n.expStrDate( opt.format, opt.strict, region ) + '$', '' ).test(value) || valid;

				if( valid===true && value ){
					var date = $.i18n.parseDate( value, opt.format, region );

					valid = date instanceof Date ? range( date.getTime(), opt.min, opt.max ) : invalid;
				}
			}
			return valid;
		},

		/**
		 * Validate a number.
		 *
		 * The `ep.validate.number()` method checks if the givn string an valid number.
		 *
		 * ### Examples
		 * Validate a number.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.date( '12,50', {format: 'n', region: 'de'} );
		 *
		 * Results:
		 *
		 *     true
		 *
		 * Validate a percent number.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.date( '12,50 %', {format: 'p2', region: 'de'} );
		 *
		 * Results:
		 *
		 *     true
		 *
		 * Validate a number with error return.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.date( '12.50', {format: 'n', region: 'de'} );
		 *
		 * Results:
		 *
		 *     NO_NUMBER
		 *
		 *
		 * ### Dependencies
		 *
		 *  + `ep`
		 *  + `ep.color`
		 *  + `jQuery.mime`
		 *  + `jQuery.i18n`
		 *
		 * @param {String} value A text to validate
		 * @param {Object} [options] A map of additional options pass to the method.
		 * @param {Boolean} options.required A boolean indication wether the value is required.
		 * @param {String} options.format A date formatter [look at the jQuery.i18n plugin].
		 * @param {String} options.region An i18n region [look at the jQuery.i18n plugin].
		 * @param {Boolean} options.strict A boolean indication wether to validate in strict mode.
		 * @param {Integer} options.min A minimum valid number.
		 * @param {Integer} options.max A maximum valid number.
		 *
		 * @method number
		 * @static
		 * @member ep.validate
		 *
		 * @since 6.11.0
		 */
		number: function( value, options ){
			value = $.trim(value);

			var opt = $.extend({
					format: 'n',
					strict: false
				},options||{}),
				region = {region:opt.region,currency:opt.currency},
				valid = required( value, opt.required );

			opt.format = i18nMap[opt.format] || opt.format;

			if( value && valid===true ){
				var msg = {
					n:'NO_NUMBER',
					c:'NO_CURRENCY',
					p:'NO_PERCENT'
				};
				opt.format.replace(/^(n|c|p)\d*$/,function(str,$1){
					valid = msg[$1] || invalid;
				});
				valid = new RegExp( '^' + $.i18n.expStrNumber( opt.format, opt.strict, region ) + '$', '' ).test(value) || valid;
			}
			if( value && valid===true ){
				var num = $.i18n.parseNumber( value, 10, region );

				valid = isNaN(num) ? invalid : range( num, opt.min, opt.max );
			}
			return valid;
		},

		/**
		 * Validate a css color.
		 *
		 * The `ep.validate.cssColor()` method checks if the givn string an css color.
		 *
		 * ### Examples
		 * Validate a css color.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.cssColor( '#336699' );
		 *
		 *     ep.validate.cssColor( 'green' );
		 *
		 *     ep.validate.cssColor( 'rgb(100,200,50)' );
		 *
		 * Results:
		 *
		 *     true
		 *
		 * Validate a css color with error return.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.cssColor( 'dunkelblau' );
		 *
		 * Results:
		 *
		 *     NO_COLOR_VALUE
		 *
		 *
		 * ### Dependencies
		 *
		 *  + `ep`
		 *  + `ep.color`
		 *  + `jQuery.mime`
		 *  + `jQuery.i18n`
		 *
		 * @param {String} value A text to validate
		 *
		 * @method cssColor
		 * @static
		 * @member ep.validate
		 *
		 * @since 6.11.0
		 */
		cssColor: function( value ){
			value = $.trim(value);
			return ep.color.stringToHex(value, true)!==undefined || 'NO_COLOR_VALUE';
		},

		/**
		 * Validate a css size.
		 *
		 * The `ep.validate.cssSize()` method checks if the givn string an valid css size.
		 *
		 * ### Examples
		 * Validate an css size.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.cssSize( '24em' );
		 *
		 * Results:
		 *
		 *     true
		 *
		 * Validate an css size with error return.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.cssSize( '24pixel' );
		 *
		 * Results:
		 *
		 *     UNKNOWN_UNIT
		 *
		 *
		 * ### Dependencies
		 *
		 *  + `ep`
		 *  + `ep.color`
		 *  + `jQuery.mime`
		 *  + `jQuery.i18n`
		 *
		 * @param {String} value A text to validate
		 * @param {Object} [options] A map of additional options pass to the method.
		 * @param {Boolean} options.required A boolean indication wether the value is required.
		 * @param {Integer} options.min A minimum valid number.
		 * @param {Integer} options.max A maximum valid number.
		 *
		 * @method cssSize
		 * @static
		 * @member ep.validate
		 *
		 * @since 6.11.0
		 */
		cssSize: function( value, options ){
			value = $.trim(value);

			var opt = $.extend({},options||{}),
				valid = required( value, opt.required );

			if( ( value || value==="" ) && valid===true ){
				switch(true){
					case (/^[0-9]+(px|pt)$/i).test(value) || /^[0-9]*\.?[0-9]+(pc|%|mm|cm|em|in|ex)$/i.test(value) || /^[0]+$/.test(value):
						valid = true;
					break;
					case (/^[0-9]+$/).test(value):
						valid = 'NO_UNIT';
					break;
					case value === "":
						valid = 'NO_UNIT_VALUE';
					break;
					case (/^[^0-9]*\.?[^0-9]/).test(value):
						valid = 'NO_CSS_NUMBER';
					break;
					case (/^[0-9]*\.[0-9]+(?:px|pt)$/i).test(value):
						valid = 'FLOAT_NOT_ALLOWED';
					break;
					case (/^[0-9]*\.[0-9]$/).test(value):
						valid = 'NO_UNIT';
					break;
					case (/^[0-9]*\.?[0-9]+[a-z]+$/).test(value):
						valid = 'UNKNOWN_UNIT';
					break;
					default:
						valid = invalid;
					break;
				}
			}
			if( value && valid===true ){
				var num = parseFloat(value.replace(/\W+$/,''),10);

				valid = isNaN(num) ? invalid : range( num, opt.min, opt.max );
			}
			return valid;
		},

		/**
		 * US zipcode validation.
		 *
		 * The `ep.validate.uszip()` method checks if five digits are given and an US address entry is selected (the hidden inputs are set).
		 *
		 */
		uszip: function( value, options ){
			var opt = $.extend({},options||{}),
				valid = required( value, opt.required ),
				i;

			if( value && valid===true ){
				if( !/^[0-9]*$/.test(value) ){
					valid = 'NOT_VALID';
				}
			}

			if( value && valid===true ){
				valid = rangelength( value, opt.minlength, opt.maxlength );
			}

			if( value && valid===true ){
				if (options.hidden) {
					for (i = 0; i < options.hidden.length; i++) {
						if ($(options.hidden[i]).val() === '') {
							valid = 'NO_ENTRY_SELECTED';
							break;
						}
					}
				}
			}
			return valid;
		},

		/**
		 * Basic validate method.
		 *
		 * The `ep.validate.basic()` method is a basic method for validation.
		 *
		 * ### Examples
		 * Validate a string.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.basic( 'Lorem ipsum ...', {
		 *         required:   true,
		 *         pattern:    '^[\w\.]+$',
		 *         minlegth:   10,
		 *         maxlength:  20
		 *     });
		 *
		 * Results:
		 *
		 *     true
		 *
		 * Validate a string with error return.
		 *
		 * JavaScript:
		 *
		 *     ep.validate.basic( 'Lorem ipsum ...', {
		 *         required:   true,
		 *         pattern:    '^[\w\.]+$',
		 *         minlegth:   10,
		 *         maxlength:  15
		 *     });
		 *
		 * Results:
		 *
		 *     NOT_IN_RANGELENGTH
		 *
		 *
		 * ### Dependencies
		 *
		 *  + `ep`
		 *  + `ep.color`
		 *  + `jQuery.mime`
		 *  + `jQuery.i18n`
		 *
		 * @param {String} value A text to validate
		 * @param {Object} [options] A map of additional options pass to the method.
		 * @param {Boolean} options.required A boolean indication wether the value is required.
		 * @param {String} options.pattern A pattern string for regular expression.
		 * @param {Integer} options.minlength A minimum number of chars.
		 * @param {Integer} options.maxlength A maximum number of chars.
		 *
		 * @method basic
		 * @static
		 * @member ep.validate
		 *
		 * @since 6.11.0
		 */
		basic: function( value, options ){
			var opt = $.extend({},options||{}),
				valid = required( value, opt.required );

			if( value && valid===true ){
				valid = pattern( value, opt.pattern);
			}

			if( value && valid===true ){
				valid = rangelength( value, opt.minlength, opt.maxlength );
			}

			return valid;
		}
/* TODO: validate by server,
		ajax: function( value, options ){

		}
*/
	});

	return ep;

});