 //------------------------------------------------------------------------------
////GLOBALS
//------------------------------------------------------------------------------
//ajax gateway url
//handles requests and connects them to Dispatcher
var ajaxGateway = '/ajax.public.php';
var validationMappings = {'phone': 'isValidUsPhone', 'zip': 'isValidUsZip'};
var formName = 'captureForm';
//------------------------------------------------------------------------------


/**
 * Validates passed input with requested validation type.
 * Uses backend to process validation.
 *
 * @author Alberto Miranda
 * @param {obj} obj
 * @param {string} validationType
 */
function validateInput(obj, validationType){
    //get validation method
    if(!validationType in validationMappings) return handleInvalidValidationType(validationType);
    var validationMethod = validationMappings[validationType];

    //if field is already valid and has not been changed exit method
    if(alreadyValid(obj.id)) return false;

    //if validation response is pending don't try to validate again, exit method
    if(pendingAjaxValidationResponse.indexOf(obj.id)!=-1) return false;

    //indicate a validation is pending for this field
    pendingAjaxValidationResponse.push(obj.id);


    //show loading status next to field
    addLoading(obj);

    //remove onblur actions and save them for later restoration
    //savedActions[obj.id] = popEvent(obj, 'onblur');
    obj.stopObserving('blur');

    //set json request
    var elementValue    = obj.value;
    var elementId       = obj.id;
    var timestamp       = getTimestamp();
    var params          = '{"action": "Validator", "method": "' + validationMethod + '", "type": "json", ' +
                          '"params": ' +
                                   '{' +
                                        '"elementValue": "' + elementValue  + '", ' +
                                        '"elementId": "'    + elementId     + '", ' +
                                        '"timestamp": "'    + timestamp     + '"' +
                                   '}' +
                          '}';
    var encodedParams   = encodeURIComponent(params);
    var ajaxCall        = new Ajax.Request(
                          ajaxGateway,
                          {
                            method: 'post',
                            parameters: 'req=' + encodedParams,
                            onComplete: validateInputCallback
                          });
}

/**
 * Handles ajax response for isValidUsPhone().
 *
 * @author Alberto Miranda
 * @param {object} response
 */
function validateInputCallback(response){
    var responseObj = getResponseObject(response);

    //if error ocurred handle it
    if(isError(responseObj)) return handleError(responseObj);

    //get result
    var valid           = responseObj.data['valid'];
    var elementId       = responseObj.data['elementId'];
    var validationType  = responseObj.data['validationType'];

    //--------------------------------------------------------------------------
    //remove this field from pending validation fields collection
    removeAjaxResponseQuery(elementId);
    //--------------------------------------------------------------------------

    //remove loading image
    removeLoading($(elementId));

    //restore observer
    Event.observe($(elementId), 'blur', function(){
        blurAction($(elementId), formName);
    });

    //--------------------------------------------------------------------------
    if(!valid) return handleInvalidInput(elementId);
    //--------------------------------------------------------------------------

    //--------------------------------------------------------------------------
    //add field to valid fields collection
    //and remove this field from invalid ajax fields collection
    addValidField(elementId);
    removeInvalidField(elementId);
    //--------------------------------------------------------------------------

    //if field is ok hide posibly shown error
    var errorId = 'jsvalidator_' + elementId;
    hideFlag(errorId, false);
    //$(errorId).hide();
}

/**
 * Highlight invalid input and show error message.
 *
 * @author Alberto Miranda
 * @param {string} elementId
 */
function handleInvalidInput(elementId){
    //display error - need jsvalidate error span!
    var errorId = 'jsvalidator_' + elementId;
    throwFlag(errorId, js_options['highlightColor'], js_options['endColor'], true); //uses jsvalidate
    //$(errorId).outerHTML = '<span class="error" id="' + errorId + '">Enter a valid US Phone.</span>';
    //Effect.Appear(errorId);
    //$(errorId).show();

    //indicate ajax validation was NOT passed for this field
    if(invalidAjaxFields.indexOf(elementId)==-1) invalidAjaxFields.push(elementId);
}

/**
 * Handles invalid validation type used.
 *
 * @author Alberto Miranda
 */
function handleInvalidValidationType(validationType){
    alert('Invalid validation type: ' + validationType);
}

/**
 * Return true if this field has already been validated and has not been
 * changed since last positive validation (valid field).
 * False if not and remove field from valid fields collection.
 */
function alreadyValid(elementId){
    if(!(elementId in validAjaxFields)) return false;
    if($F(elementId)==validAjaxFields[elementId]) return true;

    //remove from collection of valid fields
    delete validAjaxFields[elementId];
    return false;
}

/**
 * Add elementId to valid fields collection.
 *
 * @author Alberto Miranda
 * @param {string} elementId
 */
function addValidField(elementId){
    if(!(elementId in validAjaxFields)) validAjaxFields[elementId] = $F(elementId);
}

/**
 * Removes passed elementId from pendingAjaxValidationResponse array.
 * This way we stop quering the response status for this field.
 *
 * @author Alberto Miranad
 * @param {string} elementId
 */
function removeAjaxResponseQuery(elementId){
    var index = pendingAjaxValidationResponse.indexOf(elementId);
    if(index!=-1) pendingAjaxValidationResponse.splice(index, 1);
}

/**
 * Removes passed elementId from invalidAjaxFields array.
 *
 * @author Alberto Miranad
 * @param {string} elementId
 */
function removeInvalidField(elementId){
    var index = invalidAjaxFields.indexOf(elementId);
    if(index!=-1) invalidAjaxFields.splice(index, 1);
}

//------------------------------------------------------------------------------
/**
 * Return directly usable response object for passed AJAX response.
 *
 * @author Alberto Miranda
 * @param {object} response
 * @return {object}
 */
function getResponseObject(response){
    return response.responseText.evalJSON().content;
}

/**
 * Returns true if the passed response object is an error.
 * False if not.
 *
 * @author Alberto Miranda
 * @param {obj} responseObj
 * @return {boolean}
 */
function isError(responseObj){
    if(responseObj.type == undefined) return true;
    if(responseObj.type == 'err') return true;
    return false;
}

/**
 * Recieves internal error description from backend and returns its
 * corresponding frontend user friendly description.
 *
 * @author Alberto Miranda
 * @param {string} internalErrorDescription
 * @return {string}
 */
function getErrorDescription(internalErrorDescription){
    var map = new Array();
    map['dberror'] = 'There was an error with our Database. Please try, again later.';

    if(internalErrorDescription in map) return map[internalErrorDescription];
    return 'Internal error: ' + internalErrorDescription;
}

/**
 * Handles error response.
 */
function handleError(responseObj){
    var errorMessage    = 'The following Error ocurred:\n';
    var description     = getErrorDescription(responseObj.description);
    //Modalbox.show('<div class="error">' + errorMessage + description + '</div>', {title: 'System error', width: 600, overlayClose: false});
    alert(errorMessage + description);
}

/**
 * Descripción:
 * Devuelve la fecha actual en formato UNIX timestamp.
 *
 * @param
 * @return {Date} timestamp
 */
function getTimestamp(){
        d = new Date();
        timestamp = d.getTime();
        return timestamp;
}

/**
 * Adds a loading animated gif right next the passed object.
 * It helps indicate that we are doing some kind of background processing
 * related with that element.
 *
 * @author Alberto Miranda
 * @param {obj} obj
 */
function addLoading(obj){
    obj.insert({
        after: new Element('img', {src: '../images/loading.gif', id: obj.id + '_loadingImage'}).setStyle({display: 'inline', padding: '0 0 0 5px'})
    });
}

/**
 * Remove loading animated gif placed with addLoading().
 *
 * @author Alberto Miranda
 * @param {obj} obj
 */
function removeLoading(obj){
    $(obj.id + '_loadingImage').remove();
}

/**
 * Remove and return actions associated to the passed event for the passed object.
 *
 * @author Alberto Miranda
 * @param {obj} obj
 * @param {string} eventName
 */
function popEvent(obj, eventName){
    var actions = eval('obj' + '.' + eventName);
    alert(actions);
}
//----------------------------------------------------------