//
// This an internal function id to get the last validation result for each field
// NOTE: don't use a function id with this val
//
var _val_LAST_VAL_RESULT = 'last_val_result';
//
// The validation results for each field
// NOTE: don't access this field directly
//
var _val_validationResults = null;
//
// This function must be called before calling the form's validate function
// in the submit form event.
// Ex: <form id='xxxxx' onsubmit='val_resetValidation();return validate();'>
//
function val_resetValidation() {
    _val_validationResults = null;
}
//
// Sets the validation result for a validation function on a field
// @param fldID: the validated field id
// @param funID: the function id
// @param result: the result of the validation (true or false)
// NOTE: This is an internal function don't use it
//
function val_setResult(fldID, funID, result) {
    var functions = null;
    if(_val_validationResults == null) {
        _val_validationResults = new Array();
    } else {
        functions = _val_validationResults[fldID];
    }
    
    if(functions == null) {
        functions = _val_validationResults[fldID] = new Array();
    }

    functions[_val_LAST_VAL_RESULT] = functions[funID] = result;
}
//
// Gets a function validation result on a field
// @param fldID: the validated field
// @param funID: the function id
//
function val_getResult(fldID, funID) {
    var functions = null;
    if(_val_validationResults != null) {
        functions = _val_validationResults[fldID];
    }
    
    var result = true;
    if(functions != null) {
        result = utl_getDefIfNull(functions[funID], true);
    }

    return result;
}
//
// Gets the last validation result for this field
// @param fldID: the validated field
//
function val_getLastResult(fldID) {
    return val_getResult(fldID, _val_LAST_VAL_RESULT);
}

//
// This is a function id to disable all field validations
// NOTE: don't use a function id with this val
//
var _val_DISABLE_ALL_VALIDATIONS = 'disable_all_validations';
//
// Store the disabled validations for each field
// NOTE: don't access this field directly
//
var _val_disabledValidations = new Array();
//
// Use this if you want to disable a validation on a field
// @param fldID: the validated field
// @paramn funID: the function id
// @param validationDisabled: boolean val to set the disabled state
//
function val_setDisabled(fldID, funID, validationDisabled) {
    var functions = _val_disabledValidations[fldID];

    if(functions == null) {
        functions = _val_disabledValidations[fldID] = new Array();
    }

    functions[funID] = validationDisabled;
}
//
// Gets the disabled state for a validation on a field
// @param fldID: the validated field
// @paramn funID: the function id
// NOTE: returns true if all validation on the field is disabled
//
function val_isDisabled(fldID, funID) {
    var functions = _val_disabledValidations[fldID];

    var validationDisabled = false;
    if(functions != null) {
        validationDisabled = utl_getDefIfNull(functions[funID], false);
        if(!validationDisabled) {
            validationDisabled = utl_getDefIfNull(functions[_val_DISABLE_ALL_VALIDATIONS], false);
        }
    }

    return validationDisabled;
}
//
// Disables all validations on a field
// @param fldID: the validated field
// @param allValidationDisabled: boolean val to set the disabled state
//
function val_setAllDisabled(fldID, allValidationDisabled) {
    val_setDisabled(fldID, _val_DISABLE_ALL_VALIDATIONS, allValidationDisabled);
}
//
// Gets the disabled state on a field
// @param fldID: the validated field
//
function val_isAllDisabled(fldID) {
    var functions = _val_disabledValidations[fldID];

    var allValidationsDisabled = false;
    if(functions != null) {
        allValidationsDisabled = utl_getDefIfNull(functions[_val_DISABLE_ALL_VALIDATIONS], false);
    }

    return allValidationsDisabled;
}

function _val_getField(fldID) {
    var field = utl_getField(fldID);
    if(field != null && field.disabled) {
        field = null;
    }
    return field;
}
//
// Checks if tne input string is empty or not
// @param s: the input string
//
function _val_isEmpty(s) {
    return s == null || utl_getAdjustedLength(utl_trim(s)) == 0;
}

//
// Ensure that user entred a val in the field
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
function val_validateRequired(fldID, funID, cond, autoBypass) {

    // get the disabled state for this function
    var disabledValidation = val_isDisabled(fldID, funID);

    // get the last validation result
    var lastResult = true;
    if(utl_getDefIfNull(utl_getAsBoolean(autoBypass), true)) {
        lastResult = val_getLastResult(fldID);
    }

    // current validation result
    var result = true;

    // if lastResult is true and condition evaluated to true
    if(!disabledValidation && lastResult && eval(utl_getDefIfNull(cond, 'true'))) {
        // get the field        
        var field = _val_getField(fldID);
        // the field found and not disabled
        if(field != null) {
            // get field val
            var val = utl_getFieldValue(field, true);
            // no val entred
            if(val == null) {
                result = false;
            } else if(typeof val == utl_STRING_TYPE) {
                result = utl_getAdjustedLength(utl_trim(val)) > 0;
            }
        }
    }

    // set the validation result
    val_setResult(fldID, funID, result);
    return result;
}

//
// This function used for validating a min length
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param minLen: the min required length
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
function val_validateMinLength(fldID, funID, minLen, cond, autoBypass) {
    return val_validateLengthRange(fldID, funID, minLen, null, cond, autoBypass);
}
//
// This function used for validating an exact length
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param len: the required length
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
function val_validateExactLength(fldID, funID, len, cond, autoBypass) {
    return val_validateLengthRange(fldID, funID, len, len, cond, autoBypass);
}
//
// This function used for validating a max length
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param maxLen: the max required length
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
function val_validateMaxLength(fldID, funID, maxLen, cond, autoBypass) {
    return val_validateLengthRange(fldID, funID, null, maxLen, cond, autoBypass);
}
//
// This function used for validating a length range
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param min: the min required length
// @param max: the max required length
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
function val_validateLengthRange(fldID, funID, minLen, maxLen, cond, autoBypass) {
    // get the disabled state for this function
    var disabledValidation = val_isDisabled(fldID, funID);

    // get the last validation result
    var lastResult = true;
    if(utl_getDefIfNull(autoBypass, true)) {
        lastResult = val_getLastResult(fldID);
    }

    // current validation result
    var result = true;

    // if lastResult is true and condition evaluated to true
    if(!disabledValidation && lastResult && eval(utl_getDefIfNull(cond, 'true'))) {
        // get the field        
        var field = _val_getField(fldID);                    
        // the field found and not disabled
        if(field != null) {
            // get the field's val
            var val = utl_getFieldValue(field, false);
            // don't validate empty fields
            if(!_val_isEmpty(val)){
                // get the string length
                var len = utl_getAdjustedLength(val);

                minLen = utl_getAsInteger(minLen);
                maxLen = utl_getAsInteger(maxLen);

                // check if the length is out of range
                if((minLen && len < minLen) || (maxLen && len > maxLen)) {
                    result = false;
                }
            }
        }
    }

    // set the validation result
    val_setResult(fldID, funID, result);
    return result;
}

//
// Ensures that the user entred a byte val
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
var _val_BYTE_MIN = -128;
var _val_BYTE_MAX = 127;

function val_validateByte(fldID, funID, cond, autoBypass) {
    return val_validateIntegerRange(fldID, funID, _val_BYTE_MIN, _val_BYTE_MAX, cond, autoBypass);
}
//
// Ensures that the user entred a short val
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
var _val_SHORT_MIN = -32768;
var _val_SHORT_MAX = 32767;

function val_validateShort(fldID, funID, cond, autoBypass) {
    return val_validateIntegerRange(fldID, funID, _val_SHORT_MIN, _val_SHORT_MAX, cond, autoBypass);
}
//
// Ensures that the user entred an integer val
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
var _val_INTEGER_MIN = -2147483648;
var _val_INTEGER_MAX = 2147483647;

function val_validateInteger(fldID, funID, cond, autoBypass) {
    return val_validateIntegerRange(fldID, funID, _val_INTEGER_MIN, _val_INTEGER_MAX, cond, autoBypass);
}
//
// Ensures that the user entred an integer val greater than or equals min val
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param minInt: min integer val
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
function val_validateMinInteger(fldID, funID, minInt, cond, autoBypass) {
    return val_validateIntegerRange(fldID, funID, minInt, null, cond, autoBypass);
}
//
// Ensures that the user entred an integer val smaller than or equals max val
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param maxInt: max integer val
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
function val_validateMaxInteger(fldID, funID, maxInt, cond, autoBypass) {
    return val_validateIntegerRange(fldID, funID, null, maxInt, cond, autoBypass);
}
//
// Ensures that the user entred an integer val between min and max values
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param minInt: min integer val
// @param maxInt: max integer val
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
function val_validateIntegerRange(fldID, funID, minInt, maxInt, cond, autoBypass) {
    // get the disabled state for this function
    var disabledValidation = val_isDisabled(fldID, funID);

    // get the last validation result
    var lastResult = true;
    if(utl_getDefIfNull(autoBypass, true)) {
        lastResult = val_getLastResult(fldID);
    }

    // current validation result
    var result = true;

    // if lastResult is true and condition evaluated to true
    if(!disabledValidation && lastResult && eval(utl_getDefIfNull(cond, 'true'))) {
        // get the field
        var field = _val_getField(fldID);
        // the field found and not disabled
        if(field != null) {
            // get the field's val
            var val = utl_getFieldValue(field, false);

            // don't validate empty fields
            if(!_val_isEmpty(val)) {
                // get as integer
                var iValue = utl_getAsInteger(val);
                if(iValue != null) {
                    minInt = utl_getAsInteger(minInt);
                    maxInt = utl_getAsInteger(maxInt);
                    // check if the val is out of range
                    if((minInt && iValue < minInt) || (maxInt && iValue > maxInt)) {
                        result = false;
                    }
                }
            }
        }
    }

    // set the validation result
    val_setResult(fldID, funID, result);
    return result;
}

//
// Ensures that the user entred a float val
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
function val_validateFloat(fldID, funID, cond, autoBypass) {
    return val_validateFloatRange(fldID, funID, null, null, cond, autoBypass);
}
//
// Ensures that the user entred a float val greater than or equals min val
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param minFlt: the min float val
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
function val_validateMinFloat(fldID, funID, minFlt, cond, autoBypass) {
    return val_validateFloatRange(fldID, funID, minFlt, null, cond, autoBypass);
}
//
// Ensures that the user entred a float val smaller than or equals max val
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param maxFlt: the max float val
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
function val_validateMaxFloat(fldID, funID, maxFlt, cond, autoBypass) {
    return val_validateFloatRange(fldID, funID, null, maxFlt, cond, autoBypass);
}
//
// Ensures that the user entred a float val between min and max values
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param minFlt: min float val
// @param maxFlt: max float val
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
function val_validateFloatRange(fldID, funID, minFlt, maxFlt, cond, autoBypass) {
    // get the disabled state for this function
    var disabledValidation = val_isDisabled(fldID, funID);

    // get the last validation result
    var lastResult = true;
    if(utl_getDefIfNull(autoBypass, true)) {
        lastResult = val_getLastResult(fldID);
    }

    // current validation result
    var result = true;

    // if lastResult is true and condition evaluated to true
    if(!disabledValidation && lastResult && eval(utl_getDefIfNull(cond, 'true'))) {
        // get the field
        var field = _val_getField(fldID);
        // the field found and not disabled
        if(field != null) {
            // get the field's val
            var val = utl_getFieldValue(field, false);

            // don't validate empty fields
            if(!_val_isEmpty(val)) {
                // get as float
                var fValue = utl_getAsFloat(val);
                if(fValue != null) {
                    minFlt = utl_getAsFloat(minFlt);
                    maxFlt = utl_getAsFloat(maxFlt);
                    // check if the val is out of range
                    if((minFlt && fValue < minFlt) || (maxFlt && fValue > maxFlt)) {
                        result = false;
                    }
                }
            }
        }
    }

    // set the validation result
    val_setResult(fldID, funID, result);
    return result;
}

//
// Ensure that user entred digits only in the field
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
var _val_REG_EXP_DIGITS = /^\s*\d+\s*$/;

function val_validateDigits(fldID, funID, cond, autoBypass) {
    return val_validateExpression(fldID, funID, _val_REG_EXP_DIGITS, cond, autoBypass);
}
//
// Ensure that user entred integer exp. val
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
var _val_REG_EXP_INTEGER = /^\s*-?\d+\s*$/;

function val_validateIntegerExp(fldID, funID, cond, autoBypass) {
    return val_validateExpression(fldID, funID, _val_REG_EXP_INTEGER, cond, autoBypass);
}
//
// Ensure that user entred decimal exp. val
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
var _val_REG_EXP_DECIMAL = /^\s*-?\d+([.]\d+)*\s*$/;

function val_validateDecimalExp(fldID, funID, cond, autoBypass) {
    return val_validateExpression(fldID, funID, _val_REG_EXP_DECIMAL, cond, autoBypass);
}
//
// Ensure that user entred a valid e-mail address
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
function _val_createEMailExp() {
    var atom = '[^@\\(\\)\\[\\]\\\\;:",<>\\.\\s]+';
    var word = '(' + atom + ')';//'(' + atom + '| "[^"]*")';
    var rexp = '^\\s*' + word + '(\\.' + word + ')*@' + atom + '(\\.' + atom + ')*\s*$';
    return new RegExp(rexp);
}

// /^\s*([^@;:",<>\(\)\[\]\\\.\s]+)(\.[^@;:",<>\(\)\[\]\\\.\s]+)*@[^@;:",<>\(\)\[\]\\\.\s]+(\.[^@;:",<>\(\)\[\]\\\.\s]+)*\s*$/;
var _val_REG_EXP_EMAIL = _val_createEMailExp();

function val_validateEMail(fldID, funID, cond, autoBypass) {
    if(val_validateAsciiChars(fldID, funID, cond, autoBypass)) {
        return val_validateExpression(fldID, funID, _val_REG_EXP_EMAIL, cond, autoBypass);
    }
    
    return false;
}
//
// Ensures that the user entred a val matches an expression
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param rexp: the regular expression object
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
function val_validateExpression(fldID, funID, rexp, cond, autoBypass) {
    // get the disabled state for this function
    var disabledValidation = val_isDisabled(fldID, funID);

    // get the last validation result
    var lastResult = true;
    if(utl_getDefIfNull(autoBypass, true)) {
        lastResult = val_getLastResult(fldID);
    }

    // current validation result
    var result = true;

    // if lastResult is true and condition evaluated to true
    if(!disabledValidation && lastResult && eval(utl_getDefIfNull(cond, 'true'))) {
        // get the field
        var field = _val_getField(fldID);
        // the field found and not disabled
        if(field != null) {
            // get the field's val
            var val = utl_getFieldValue(field, false);            
            // don't validate empty fields
            if(!_val_isEmpty(val)) {
                result = rexp.test(val);                
            }
        }
    }

    // set the validation result
    val_setResult(fldID, funID, result);
    return result;
}
//
// Ensures that the user entred a string that contains only ascii characheters
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
function val_validateAsciiChars(fldID, funID, cond, autoBypass) {
    // get the disabled state for this function
    var disabledValidation = val_isDisabled(fldID, funID);

    // get the last validation result
    var lastResult = true;
    if(utl_getDefIfNull(autoBypass, true)) {
        lastResult = val_getLastResult(fldID);
    }

    // current validation result
    var result = true;

    // if lastResult is true and condition evaluated to true
    if(!disabledValidation && lastResult && eval(utl_getDefIfNull(cond, 'true'))) {
        // get the field
        var field = _val_getField(fldID);
        // the field found and not disabled
        if(field != null) {
            // get the field's val
            var val = utl_getFieldValue(field, false);            
            // don't validate empty fields
            if(!_val_isEmpty(val)) {
                result = utl_isAsciiChars(val);                
            }
        }
    }

    // set the validation result
    val_setResult(fldID, funID, result);
    return result;
}
//
// This field will be used for passing the field's val to the custom validation
// NOTE: don't access this field directly
//
var _val_current_value = null;
var _val_current_params = null;
//
// Custom validation
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param funName: the javascript function's name,
// must take the field's val as a parameter
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
function val_validateCustom(fldID, funID, funName, cond, autoBypass) {
    // get the disabled state for this function
    var disabledValidation = val_isDisabled(fldID, funID);

    // get the last validation result
    var lastResult = true;
    if(utl_getDefIfNull(autoBypass, true)) {
        lastResult = val_getLastResult(fldID);
    }

    // current validation result
    var result = true;

    // if lastResult is true and condition evaluated to true
    if(!disabledValidation && lastResult && eval(utl_getDefIfNull(cond, 'true'))) {
        // get the field
        var field = _val_getField(fldID);
        // the field found and not disabled
        if(field != null) {
            // get the field's val
            var val = utl_getFieldValue(field, false);

            // don't validate empty fields
            if(!_val_isEmpty(val)) {
                _val_current_value = val;
                result = eval(funName + '("' + fldID + '", _val_current_value)');
                _val_current_value = null;
            }
        }
    }

    // set the validation result
    val_setResult(fldID, funID, result);
    return result;
}
//
// Advanced custom validation
// @param fldID: the id of the field that will be validated
// @param funID: the function id that will be used in saving the validation result
// @param funName: the javascript function's name,
// must take the field's val as a parameter and the other passed parameters
// @param params: the parameters that will be passed to the function
// @param cond: the validation condition, the default val is 'true'
// @param autoBypass: indicates if we are going to bypass this validation if the last
//      validation was failed, the default val is true
//
function val_validateAdvancedCustom(fldID, funID, funName, params, cond, autoBypass) {
    // get the disabled state for this function
    var disabledValidation = val_isDisabled(fldID, funID);

    // get the last validation result
    var lastResult = true;
    if(utl_getDefIfNull(autoBypass, true)) {
        lastResult = val_getLastResult(fldID);
    }

    // current validation result
    var result = true;

    // if lastResult is true and condition evaluated to true
    if(!disabledValidation && lastResult && eval(utl_getDefIfNull(cond, 'true'))) {
        // get the field
        var field = _val_getField(fldID);
        // the field found and not disabled
        if(field != null) {
            // get the field's val
            _val_current_value = utl_getFieldValue(field, true);
            _val_current_params = params;
            result = eval(funName + '("' + fldID + '", _val_current_value, _val_current_params)');
            _val_current_value = null;
            _val_current_params = null;
        }
    }

    // set the validation result
    val_setResult(fldID, funID, result);
    return result;
}

//
// allow numbers only on key press event
// @param e: this is the event object , this value will be used if the browser isn't IE
// @param cnd: the validation condition, the default val is 'true'
//
function val_keyPressAllowNumbersOnly(e, cnd) {
    // test the condition
    if(!utl_getDefIfNull(utl_getAsBoolean(utl_getExpValue(cnd)), true)) {
        return;
    }
            
    //This function will allow enter key
    if(window.event) {
        e = window.event;
        var charCode = e.keyCode;
        if (charCode && charCode != 13 && (charCode < 48 || charCode > 57)) {
            e.returnValue = false;
        }
    } else if(e && utl_isFunction(e.preventDefault)) {
        var charCode = e.charCode ?  e.charCode : e.which;
        if (charCode && charCode != 13 && (charCode < 48 || charCode > 57)) {
            e.preventDefault();
        }
    }
}
