/**
 *
 * Módulo que contiene funciones javascript que nos ayudarán
 * a la validación de formularios
 *
 */
 
 
/**
 *
 * Declaracion de constantes
 * 
 */
// OPERACIONES PARA LA FUNCION IsComparisonOK
var EQ = "==";
var NE = "!=";
var GT = ">";
var LT = "<";
var GET = ">=";
var LET = "<=";
/**
 *
 * Definicion de clases
 * 
 */
/**
 * DEFINICION DE LA CLASE FormInfo
 */
/**
 * Constructor de la clase FormInfo
 *
 */
function FormInfo()
{
    // info
    this.formfields = new Array();
    // methods
    this.addFormField = addFormField;
    this.getFormFields = getFormFields;
}
/**
 * FormInfo::addFormField
 * Añade un nuevo objeto FormField al vector de campos
 */
function addFormField( objFormField )
{
    var nIndex = this.formfields.length;
    this.formfields[nIndex] = objFormField;
}
/**
 * FormInfo::getFormFields
 * Devuelve el vector de objetos campos del formulario
 */
function getFormFields()
{
    return( this.formfields );
}



/**
 * DEFINICION DE LA CLASE FormField
 */
/**
 * Constructor de la clase FormField
 *
 *    @param sName               nombre del campo del formulario
 *
 */
function FormField( sName )
{
    // info
    this.name = sName;
    this.restrictions = new Array();
    // methods
    this.addRestriction = addRestr;
    this.getName = getFieldName;
    this.getRestrictions= getFieldRestrictions;
}

/**
 * FormField::addRestr
 * Añade una restriccion al vector de restricciones del campo
 */
function addRestr( sCondition, sResponse )
{
    var nIndex = this.restrictions.length;
    this.restrictions[nIndex] = new Array(2);
    this.restrictions[nIndex][0] = sCondition;
    this.restrictions[nIndex][1] = sResponse;
}

/**
 * FormField::getFieldName
 * Devuelve el nombre del campo
 */
function getFieldName()
{
    return( this.name );
}

/**
 * FormField::getFieldRestrictions
 * Devuelve el vector de restricciones del campo
 */
function getFieldRestrictions()
{
    return( this.restrictions );
}




/**
 *
 * Declaracion de funciones
 * 
 */
/**
 *
 * Funcion que recibe un vector de objetos de la clase FormField con la 
 * información de los campos a los que hay que realizar las validaciones
 * del formulario pasado como parametro
 *
 * El formato del vector es el siguiente:
 *
 *        vFieldsInfo[i] - objeto de la clase FormField
 *
 *    @param vFieldsInfo          vector con la info para realizar las validaciones de los campos
 *    @param objForm              objeto Formulario a validar
 *
 */
function validateForm( vFieldsInfo, objForm )
{
    //LOG::alert( "validateForm:: Dentro de la funcion" );
    

    var i;
    var sField;
    var sType;
    var vRestric;
    var bValue;
    // nos recorremos el vector de objetos para realizar las validaciones
    //LOG::alert( "validateForm:: Antes del bucle" );
    for( i=0; i < vFieldsInfo.length; i++ )
    {

        // capturamos el nombre del campo mediante el metodo getName() y comprobamos si ese
        // campo existe en el formulario
        // si la funcion devuelve falso, es que hay un error y salimos de 
        // la funcion ( el alert correspondiente lo ha puesto la funcion llamada )
        //LOG::alert( "validateForm::Iteracion " + i );
        sField = vFieldsInfo[i].getName();
        //LOG::alert( "validateForm::Iteracion " + i + "::sField = '" + sField + "'" );
        bValue = Is_Field_In_Form( sField, objForm );
        
        if( !bValue )
        {
            //LOG::alert( "validateForm::Iteracion " + i + "::ERROR Fuera de la funcion" );
            return false;
        }
        
       
        // capturamos ahora el vector de restricciones asociado al campo
        // y llamamos a la funcion encargada de evaluar estas restricciones
        // si la funcion devuelve falso, es que hay un error y salimos de 
        // la funcion ( el alert correspondiente lo ha puesto la funcion llamada)
        objField = objForm.elements[sField];
     
        vRestric = new Array();
        vRestric = vFieldsInfo[i].getRestrictions();
        //LOG::alert( "validateForm::Iteracion " + i + "::vRestric[0][0] = '" + vRestric[0][0] + "'" );
        //LOG::alert( "validateForm::Iteracion " + i + "::vRestric[0][1] = '" + vRestric[0][1] + "'" );
        bValue = Is_FieldRestrictions_OK( vRestric, objField );
        //Ojo al dato: este "if" hace que las validaciones en b_validate.js se hagan AL REVES :-(
        if( !bValue )
        {
            //LOG::alert( "validateForm::Iteracion " + i + "::ERROR Fuera de la funcion" );
            return false;
        }

    }

    //LOG::alert( "validateForm:: Fin del bucle" );
    //LOG::alert( "validateForm:: Fuera de la funcion" );
    // si salimos por aqui es que el formulario esta validado correctamente
    return true;
}



/**
 *
 * Funcion que recibe el nombre de un campo y un objeto formulario y devuelve
 * True si uno de los campos del formulario tiene ese nombre
 * False en caso contrario
 *
 *    @param sField               nombre de campo
 *    @param objForm              objeto Formulario 
 *
 */
function Is_Field_In_Form( sField, objForm )
{
   //LOG::alert( "Is_Field_In_Form:: Dentro de la funcion" );
    if( objForm.elements[sField] )
    {
       //LOG::alert( "Is_Field_In_Form::TRUE Fuera de la funcion" );
        return true;
    }
    else
    {
        alert( "Funcion Is_Field_In_Form\nERROR en desarrollo\n\nEl campo '" + sField + "' especificado en el vector de validacion de campos no existe en el formulario '" + objForm.name + "'.\nRevisar que el vector de validación de campos pasado como parámetro es el correspondiente al formulario actual." );
       //LOG::alert( "Is_Field_In_Form::FALSE Fuera de la funcion" );
        return false;
    }
}


/**
 *
 * Funcion que recibe un vector de restricciones y un objeto campo
 * La función devuelve True si el objField cumple todas las restricciones incluidas en
 * el vector de restricciones y False en caso contrario
 *
 * El formato del vector es el siguiente:
 *
 *        vRestric[i][0] - llamada a funcion existente que devuelve True o False
 *        vRestric[i][1] - respuesta a realizar en caso de que la funcion devuelva False
 *
 *    @param vRestric               vector de restricciones
 *    @param objField               objeto campo
 *
 */
function Is_FieldRestrictions_OK ( vRestric, objField )
{
    var i;
    var bValue;
    var sCondition;
    var sResponse;
    
    //LOG::alert( "Is_FieldRestrictions_OK::Dentro de la funcion" );
    // en primer lugar nos recorremos el vector de restricciones para ir comprobando cada una
    // de ellas
    for( i=0; i < vRestric.length; i++ )
    {

        // recogemos la condicion y el mensaje a mostrar si no se cumple la restriccion
        sCondition = vRestric[i][0];

        sResponse = vRestric[i][1];
        bValue = eval( sCondition );
        //alert("condicion=" + sCondition + "\nresultado=" + bValue);

        //LOG::alert( "Is_FieldRestrictions_OK::bValue = '" + bValue + "'" );
        if( !bValue )
        {
            eval( sResponse );
            //alert("focus on=" + objField.name );     
            objField.focus();
            objField.blur();
            if ( ( objField.type != "select-multiple" ) && ( objField.type != "select-one") )
                objField.select();
                
            //LOG::alert( "Is_FieldRestrictions_OK::FALSE Fuera de la funcion" );
            return false;
        }
    }
    //LOG::alert( "Is_FieldRestrictions_OK::TRUE Fuera de la funcion" );
    return true;    
}



/**
 * FUNCIONES DE VALIDACION DE VALORES
 */

/**
 *
 * Dado un valor, devuelve True si es numerico, teniendo en cuenta que el separador
 * decimal es el pasado como parametro
 *
 *    @param sValue               valor para comprobar si es numerico
 *    @param sDecSep                 caracter separador decimal 
 *
 */
function IsNumeric( sValue, sDecSep ) 
{
    var flag = 0;
    var i;

    for ( i = 0 ; i < sValue.length ; i++ )
    if ( sValue.charAt(i) < '0' || sValue.charAt(i) > '9' ) 
    {
        if ( sValue.charAt(i) == sDecSep ) 
        {
            if ( flag == 1 )
                return false;
            else
                flag = 1;
        }
        else
            return false;
    }
    return true;
}


/**
 *
 * Dado un valor, devuelve True si es entero y False en caso contrario
 *
 *    @param sValue               valor para comprobar si es entero
 *
 */
function IsInteger( sValue ) 
{
    for ( var i = 0 ; i < sValue.length ; i++ )
        if ( sValue.charAt(i) < '0' || sValue.charAt(i) > '9' )
            return false;
 
    return true;
}


/** 
 * Dado un valor, comprueba que es una fecha con el formato dd/mm/aaaa.
 * Se devuelve True en caso afirmativo , sino False.
 * Se hace una comprobación sintáctica y semántica.
 *
 *    @param sValue               valor que contiene la fecha
 *
 */
function IsDateDDMMAAAA( sValue )
{  
    var i;
    var tam = sValue.length;
    var barra1 , barra2;
    var dia = sValue.charAt(0)+sValue.charAt(1);
    var mes = sValue.charAt(3)+sValue.charAt(4);
    var anio= sValue.charAt(6)+sValue.charAt(7)+sValue.charAt(8)+sValue.charAt(9);

    // Comprobacion sintáctica
    if ( tam == 0 )
        return true;
    if ( tam != 10 )
        return false;
    if ( sValue.charAt( 2 ) != '/' )
        return false;
    if ( sValue.charAt( 5 ) != '/' )
        return false;
    for ( i = 0 ; i < tam ; i++ )
    {
        if ( i != 2 && i != 5 )
            if ( sValue.charAt(i) < '0' || sValue.charAt(i) > '9' )
                return false;
    }
    
    if( mes.substring( 0, 1) == '0')
    	mes = mes.substring(1,2 );
    	
    // Comprobación semántica :
    if ( mes > 12 )
        return false;
    switch ( parseInt( mes ) )
    {
        case 1: case 3: case 5: case 7: case 8: case 10: case 12:
            if ( dia > 31 )
                return false;
            break;
        case 4: case 6: case 9: case 11:
            if ( dia > 30 )
                return false;
            break;
        case 2 :
        { 
            xano = parseInt( anio );
           //LOG::alert( xano + " " + dia );      
            if ( ( xano % 400  == 0 || ( xano % 100 != 0 &&  xano % 4 == 0 ) ) )
                if ( parseInt( dia ) > 29 )
                    return false;
            else 
                if ( parseInt( dia ) > 28 )
                    return false;
            break;
        }
        default : 
            return false;
    }
    return true;
}

/** 
 * Dado un valor, comprueba si nos llega vacio, en caso contrario comprueba que nos llega una fecha
 * Se devuelve True en caso afirmativo , sino False.
 * Se hace una comprobación sintáctica y semántica.
 *
 *    @param sValue               valor que contiene la fecha
 *
 */
function CheckDateEmptyDDMMAAAA( sValue )
{  
    sValue = Trim( sValue )
    
    if( sValue.length == 0 )
    	return true
    else
        return NewIsDateDDMMAAAA( sValue )    	
}


function IsDateDD( sValue )
{  
	
    var i;
    var tam = sValue.length;
    var barra1 , barra2;
    var dia = sValue.charAt(0)+sValue.charAt(1);
    
    alert("dia[[[" + dia + "]]]<br>");

    // Comprobacion sintáctica
    if ( tam == 0 )
        return true;
    if ( tam != 2 )
        return false;
    for ( i = 0 ; i < tam ; i++ )
    {
    	alert("i: " + i + "<br>")
        if ( sValue.charAt(i) < '0' || sValue.charAt(i) > '9' )
             return false;
    }
    return true;
}
function IsDateMM( sValue ){
 
    var dia;
    
    var mes = sValue.charAt(0)+sValue.charAt(1);
    
    alert("mes[" + mes + "]<br>");
    
    // Comprobación semántica :
    if ( mes > 12 )
        return false;
    switch ( parseInt( mes ) )
    {
        case 1: case 3: case 5: case 7: case 8: case 10: case 12:
            if ( dia > 31 )
                return false;
            break;
        case 4: case 6: case 9: case 11:
            if ( dia > 30 )
                return false;
            break;
      
    }
    return true;
}

function IsDateAAAA( sValue ){
	
    	
    //var anio= sValue.charAt(6)+sValue.charAt(7)+sValue.charAt(8)+sValue.charAt(9);
    
    var anio= sValue.charAt(0)+sValue.charAt(1)+sValue.charAt(2)+sValue.charAt(3);
    var dia;
    var xano;
    
    alert("anio[" + anio + "]<br>");
    
    switch ( parseInt( anio ) )
    {
    	case 1 :
        { 
            xano = parseInt( anio );
            alert("xano{{" + xano + "}}<br>")
           //LOG::alert( xano + " " + dia );      
            if ( ( xano % 400  == 0 || ( xano % 100 != 0 &&  xano % 4 == 0 ) ) )
                if ( parseInt( dia ) > 29 )
                    return false;
            else 
                if ( parseInt( dia ) > 28 )
                    return false;
            break;
        }
        default : 
            return false;
    }
    return true;
}


/** 
 * Dado un valor, comprueba si esta vacío o no
 *
 *    @param sValue               valor a comprobar
 *
 */
function IsEmpty( sValue ) 
{
    sValue = Trim( sValue );
    return ( sValue.length == 0 );

}



/** 
 * Dado un valor, quita los espacios en blanco por delante y por detras
 *
 *    @param sValue               valor del que quitar los espacios en blanco
 *
 */
function Trim( sValue )
{
    var i;
    var sValueAux=sValue;
        
    for ( i = 0; i < sValue.length; i++ )
    {
        if( sValue.charAt(i) == " " )
            sValueAux = sValue.substring( i+1, sValue.length );
        else
            break;
    }
    sValue = sValueAux;
    
    for( i = sValueAux.length-1; i >= 0; i--)
    {
        if( sValueAux.charAt(i) == " " )
            sValue = sValueAux.substring( 0, i );
        else
            break;
    }
    
    return( sValue );
}


/** 
 * Dado dos valores, los compara mediante el operador tambien pasado como parametro
 *
 *    @param sValue1              primer valor a comparar
 *    @param sOperator            operador de comparacion
 *    @param sValue2              segundo valor a comparar
 *
 */
function IsCompareOK( sValue1, sOperator, sValue2 )
{
    if( eval( sValue1 + sOperator + sValue2 ) )
        return true;
    
    return false;
}


/** 
 * Dado un valor, indica si tiene formato de email o no
 *
 *    @param sValue1              valor a contrastar si es email
 *
 */
function IsEmail( sValue ) {
    var supported = 0;
    if (window.RegExp) {
        var tempStr = "a";
        var tempReg = new RegExp(tempStr);
        if (tempReg.test(tempStr)) supported = 1;
    }

    if (!supported) 
        return (sValue.indexOf(".") > 2) && (sValue.indexOf("@") > 0);

    var r1 = new RegExp("(@.*@)|(\\.\\.)|(@\\.)|(^\\.)");
    var r2 = new RegExp("^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$");
    
    return (!r1.test(sValue) && r2.test(sValue));
    
}

/**
 *
 * Dado un valor, devuelve True si su longitud es > que su segundo parametro
 *
 *    @param sValue               valor a comprobar
 *    @param MaxLen               longitud a comprobar
 *
 */
function hasMoreLen( value, MaxLen ) 
{
    var sTemp = new String(value);
    return (sTemp.length > MaxLen);
    sTemp = null;
}

/**
 *
 * Dado un valor, devuelve True si contiene al menos una letra
 *
 *    @param sValue               valor a comprobar
 *
 */
function hasText( sValue ) 
{
    var len = sValue.length;

    for ( var i = 0; i < len; i++ )
    {
        if (   (sValue.charAt(i) >= 'a' && sValue.charAt(i) <= 'z')
            || (sValue.charAt(i) >= 'A' && sValue.charAt(i) <= 'Z'))
        {
            return true;
        }
    }
    return false;
}

/**
 *
 * Dado un valor, devuelve True si contiene al menos una letra
 *
 *    @param sValue               valor a comprobar
 *
 */
function hasNumber( sValue ) 
{
    var len = sValue.length;

    for ( var i = 0; i < len; i++ )
    {
        if ( sValue.charAt(i) >= '0' && sValue.charAt(i) <= '9')
        {
            return true;
        }
    }
    return false;
}

/**
 *
 * Dado un valor, devuelve True si es numerico, teniendo en cuenta que los separador(es)
 * decimal(es) pasado(s) como parametro
 *
 *    @param sValue               valor para comprobar si es numerico
 *    @param sSeparadores         caracter(es) separador(es) (se dan por validos)
 *
 */
function isNumero( sValue, sSeparadores ) 
{

    var len = sValue.length;

    for ( var i = 0 ; i < len ; i++ )
    {
        if ( sValue.charAt(i) < '0' || sValue.charAt(i) > '9'  ) 
        {
            // Si esta entre los separadores que nos han pasado, no hacemos na
            if ( sSeparadores.indexOf( sValue.charAt(i) ) != -1 )
                continue;
            else
                return false;
        }
    }
    return true;
}

/**
 *
 * Dado un valor, devuelve su longitud dando la posibilidad de que algunos caracteres no cuenten 
 * dando la posibilidad de que algunos caracteres no cuenten en la comparacion
 *
 *    @param sValue               valor a comprobar
 *    @param MaxLen               longitud a comprobar
 */
function getLongitud( sValue, sNoCuentan )
{
    var len = sValue.length; 
    var iCont = 0;   
    
    for ( var i = 0 ; i < len; i++ )
    {
        if ( sNoCuentan.indexOf( sValue.charAt(i) ) != -1 )
            continue;
        else
            iCont++;
    }
    return iCont;
}

/**
 *
 * Dado un valor, devuelve True si su longitud es > que su segundo parametro
 * dando la posibilidad de que algunos caracteres no cuenten en la comparacion
 *
 *    @param sValue               valor a comprobar
 *    @param MaxLen               longitud a comprobar
 *    @param sNoCuentan           caracter(es) que no cuentan  
 */
function isTooLong( sValue, iMax, sNoCuentan )
{
    if ( sNoCuentan != null )
        return ( iMax < getLongitud( sValue, sNoCuentan ) );
    else
        return ( hasMoreLen( sValue, iMax ) );
    
}

/** 
 * Dado un valor, comprueba que es una fecha con el formato dd/mm/aaaa.
 * Se devuelve True en caso afirmativo , sino False.
 * Se hace una comprobación sintáctica y semántica.
 *
 *    @param sValue               valor que contiene la fecha
 *
 * Es igual que IsDateDDMMAAAA pero modificada ya que no funciona correctamente
 */
function NewIsDateDDMMAAAA( sValue )
{  
    var i;
    var tam = sValue.length;
    var barra1 , barra2;
    var dia = sValue.charAt(0)+sValue.charAt(1);
    var mes = sValue.charAt(3)+sValue.charAt(4);
    var anio= sValue.charAt(6)+sValue.charAt(7)+sValue.charAt(8)+sValue.charAt(9);

    // Comprobacion sintáctica
    if ( tam == 0 )
        return false;
    if ( tam != 10 )
        return false;
    if ( sValue.charAt( 2 ) != '/' )
        return false;
    if ( sValue.charAt( 5 ) != '/' )
        return false;
    for ( i = 0 ; i < tam ; i++ )
    {
        if ( i != 2 && i != 5 )
            if ( sValue.charAt(i) < '0' || sValue.charAt(i) > '9' )
                return false;
    }
 
    // Comprobación semántica :
    if ( mes > 12 )
        return false;
    if ( dia > 31 )
        return false;
    switch ( parseInt( mes ) )
    {
        case 1: case 3: case 5: case 7: case 8: case 10: case 12:
            if ( dia > 31 )
                return false;
            break;
        case 4: case 6: case 9: case 11:
            if ( dia > 30 )
                return false;
            break;
        case 2 :
        { 
            xano = parseInt( anio );
           //LOG::alert( xano + " " + dia );      
            if ( ( xano % 400  == 0 || ( xano % 100 != 0 &&  xano % 4 == 0 ) ) )
                if ( parseInt( dia ) > 29 )
                    return false;
            else 
                if ( parseInt( dia ) > 28 )
                    return false;
            break;
        }
    }
    return true;
}

/**
* Dada una cadena con tags variables %n%, devuelve otra con dichos tags sustituidos
* por las cadenas que se le pasan a la función como argumentos. Soporta un máximo de
* 10 cadenas variables 0-9. Se usa base 0 para los argumentos
*/
function p_VarMsg()
{
   if( arguments.length < 1 ) return "[p_VarMsg ERROR] No arguments";

   var expresion_regular    = new RegExp("%\\d%",'g');
   //var expresion_regular    = /%\d%/g;
   var s_buff     = arguments[ 0 ];
   var tmp_buff   = null;
   var iPos = 0;
   if( expresion_regular.test( s_buff ) )
   {
       while( (tmp_buff = expresion_regular.exec( s_buff )) != null )
       {
           iPos = expresion_regular.lastIndex;
           tmp_buff = new String( expresion_regular.exec( s_buff ) );
           if (expresion_regular.lastIndex)
              s_buff = s_buff.substring( 0, expresion_regular.lastIndex - tmp_buff.length ) + 
                    arguments[parseInt(tmp_buff.charAt( 1 ))+1] +
                    s_buff.substring( expresion_regular.lastIndex, s_buff.length );
           else // Parece que en ocasiones el valor expresion_regular.lastIndex = undefined. Hacemos una chapucilla para que no se embucle MIRARLO!!!!!!!!!!!!!!
           {

              s_buff = s_buff.substring( 0, s_buff.indexOf('%') ) + 
                    arguments[parseInt(tmp_buff.charAt( 1 ))+1] +
                    s_buff.substring( s_buff.indexOf('%') + 3, s_buff.length );
           }  
       }    
   }     
   return s_buff;
}

/**
* Se encarga de mostrar el mensaje de error en los formularios
* Solo muestra un mensaje
*/
function p_Msg()
{
   if( arguments.length < 1 ) return "[p_Msg ERROR] No arguments";

   var s_msg     = arguments[ 0 ];
   var s_campo   = arguments[ 1 ];

   var inicio = s_msg.indexOf('%');
   var fin = s_msg.indexOf('%', inicio);
   
   if( inicio != -1 && fin  != -1 )
   	   s_msg = s_msg.substring( 0, s_msg.indexOf('%') ) + s_campo +
           s_msg.substring( s_msg.indexOf('%') + 3, s_msg.length );
   
 
   return s_msg;
}


function IsHHMM( sValue ) 
{
    var i;
    var tam = sValue.length;
    var hh = sValue.charAt(0)+sValue.charAt(1);
    var mm = sValue.charAt(3)+sValue.charAt(4);

    // Comprobacion sintáctica
    if ( tam == 0 )
        return false;
    if ( tam != 5 )
        return false;
    if ( sValue.charAt( 2 ) != ':' )
        return false;
    
    for ( i = 0 ; i < tam ; i++ )
    {
        if ( i != 2 && i != 5 )
            if ( sValue.charAt(i) < '0' || sValue.charAt(i) > '9' )
                return false;
    }
    return true;
}

