/*
	Elimina espacios duplicados de una cadena 
	Argumentos:
		value: cadena a procesar
		mode: opciones de eliminacion
			mode ::= L|R|A
			L ==> elimina espcios duplicados a la izquierda de la cadena
			R ==> elimina espcios duplicados a la derecha de la cadena
			A ==> elimina espcios duplicados en toda la cadena
	Retorno: el resultado de eliminar los espacios duplicados de la cadena segun el modo especificado
	JScript Level: 1
*/
function trim(value, mode)
{

	if (value==null || value.length==0) return value;
	if (mode==null) mode = 'A';
	mode = mode.toUpperCase();
	if (mode=='N') return value;
	var result = value;
	if (mode=='L' || mode=='A')
		result = result.replace(/^\x20+/,'');
	if (mode=='R' || mode=='A')
		result = result.replace(/\x20+$/,'');
	if (mode=='A')
		for(;result!=result.replace(/\x20\x20/g,' ');result=result.replace(/\x20\x20/g, ' '));
	return result;
}



/* ************************************************************************************** */
/* ESTRUCTURA DE FUNCIONES DE VALIDACION                                                  */
/* ************************************************************************************** */
var Validators = null;

function RegisterValidator(oValidatorType)
{
	if (Validators==null) Validators = new Array();
	Validators[oValidatorType.Type] = oValidatorType;
}


//--------
function ValidatorType(type, fn_validate)
{
	this.Type = type;
	this.Validate = fn_validate;	//retorna la representacion del valor o null
	return this;
}

/*
	Funcion prototipo para validar expresiones regulares en gral.
	Argumentos:
		value (string): Valor a verificar
		regexp (regular expression): Expresion regular verificadora
	Retorno:
		Si valor cumple con regexp, valor, de lo contrario null.
*/
function validator_fn_regular_expression(value, regexp)
{
	if (arguments.length!=2) 
		throw('regular_expression validator: insufficient arguments. Use fn(value, regexp)');
	var result = regexp.test(value);
	return (result) ? value : null;
}

/*
	Funcion prototipo para validar fechas.
	Argumentos:
		valor (string):  Valor a verificar
		regexp (regular expression): Expresion regular para parsear el valor de la fecha.
			Esta expresion regular debe contener los patrones de captura de las partes año, mes y días de la fecha.
		format (string): String de formato de fecha
			format ::= atom-atom-atom
			atom ::= day|month|year
		min (string, opcional): una fecha en el mismo formato esperado para valor. 
			Si se especifica, valor deberá ser mayor que min
		max (string, opcional): una fecha en el mismo formato esperado para valor. 
			Si se especifica, valor deberá ser menor que max 
	Retorno:
		En caso de exito, retorna un objeto fecha con el valor de la fecha correspondiente a valor,
		de lo contrario, retorna null.
*/
function validator_fn_date(value, regexp, format)
{
	if (arguments.length<3)
		throw('date validator: insufficient arguments. Use fn(value, regexp, format, [min], [max])');
		
	var dp = format.split('-');
	var vMatch = value.match(regexp);
	if (vMatch==null) return null;
	if (dp.length!=(vMatch.length-1)) {
		delete vMatch;
		return null;
	}
	
	var ds = new Array();
	ds.day = ds.month = ds.year = 0;
	for(i=0;i<dp.length;i++) 
		eval('ds.' + dp[i] + ' = ' + vMatch[i+1]);
	var dt = new Date(ds.year, ds.month-1, ds.day);
	result = (dt.getDate()==ds.day && dt.getMonth()==(ds.month-1) && (dt.getYear()==ds.year || dt.getFullYear()==ds.year))
	if (result && arguments.length>3) {
		var dmin = (arguments[3]!=null) ? validator_fn_date(arguments[3], regexp, format) : null;
		if (dmin!=null) {
			result = result && (dt.valueOf()>dmin.valueOf());
			delete dmin;
		}
		if (result && arguments.length==5) {
			var dmax = validator_fn_date(arguments[4], regexp, format);
			if (dmax!=null) {
				result = result && (dt.valueOf()<dmax.valueOf());
				delete dmax;
			}
		}
	}
	delete ds;
	delete vMatch;
	return (result) ? dt : null;
}


/*
	Funcion prototipo para validar numeros enteros.
	Argumentos:
		value (string): Valor a verificar
		min (string, opcional): un numero en el mismo formato esperado para valor. 
			Si se especifica, valor deberá ser mayor que min
		max (string, opcional): un numero en el mismo formato esperado para valor. 
			Si se especifica, valor deberá ser menor que max 
	Retorno:
		Si valor cumple con regexp, el nro. representado por valor, de lo contrario null.
*/
function validator_fn_integer(value)
{
	if (arguments.length!=1) 
		throw('integer validator: insufficient arguments. Use fn(value)');
	var value = validator_fn_regular_expression(value, /[0-9]*/);
	if (value==null) return null;
	var integerValue = Number(value);
	var result = (integerValue.toString() == value);
	return (result) ? integerValue : null;
}


/*
	Funcion prototipo para validar numeros con punto flotante.
	Argumentos:
		value (string): Valor a verificar
		regexp (regular expression): Expresion regular para la representacion del nro.
			Debe contener el patron de captura para el separador decimal.
		min (string, opcional): un numero en el mismo formato esperado para valor. 
			Si se especifica, valor deberá ser mayor que min
		max (string, opcional): un numero en el mismo formato esperado para valor. 
			Si se especifica, valor deberá ser menor que max 
	Retorno:
		Si valor cumple con regexp, el nro. representado por valor, de lo contrario null.
*/
function validator_fn_real(value, regexp)
{
	if (arguments.length!=2) 
		throw('real validator: insufficient arguments. Use fn(value, regexp)');
	var vMatch = value.match(regexp);
	if (vMatch==null) 
		return null;
	if (vMatch.length!=2) 
		throw('real validator: regexp erronea. No incluye el patrón de captura del separador decimal');
	var realValue = (vMatch[1]!='') ? Number(value.replace(vMatch[1],'.')) : Number(value);
	var result = !isNaN(realValue);
	return (result) ? realValue : null;
}


RegisterValidator(new ValidatorType('regular_expression', validator_fn_regular_expression));
RegisterValidator(new ValidatorType('date', validator_fn_date));
RegisterValidator(new ValidatorType('integer', validator_fn_integer));	
RegisterValidator(new ValidatorType('real', validator_fn_real));	
