function formValidationNotify(options)
{
    var field = options.field?options.field:this;

    // by agreement div for error messages of form should have id formIdErrorMsgs
    var formErrorMsgsId = $(field).closest('form').attr('id')+'ErrorMsgs';
    var fieldErrorMessageId = formErrorMsgsId+$(field).attr('id');

    
    switch(options.status)
    {

    case 'pass':
        // remove error messages
        $(field).removeClass('form-error');
        $('#'+$(field).attr('id')+'+div.error-message').remove();
        $('#'+fieldErrorMessageId).remove();

        // add success if necessary
        $(field).addClass('field-valid');
        if (options.prompt)
        {
            // there is no message yet
            if ($('#'+$(field).attr('id')+'+div.successMessage').length==0)
            {
                // add it
                $(field).after('<div class="successMessage">'+options.prompt+'</div>');
            }
            else
            {
                // replace it
                $('#'+$(field).attr('id')+'+div.successMessage').html(options.prompt);
            }
            
        }
        break;
    case 'fail':
        // check if field is already in error state
        /*if (!$(field).hasClass('form-error'))
          {*/
            $(field).addClass('form-error');
            $('#'+$(field).attr('id')+'+div.successMessage').remove();
            if(options.prompt)
            {
                // div containing error for message exists, insert message in it
                if($('#'+fieldErrorMessageId).length)
                {
                    $('#'+fieldErrorMessageId).html(options.prompt); 
                }
                else
                {
                    if (options.hightlightError)
                    {
                        $('#'+formErrorMsgsId).append('<div id="'+fieldErrorMessageId+'" class="errorMessageHighlight">'+options.prompt+'</div>');
                    }
                    else
                    {
                        $('#'+formErrorMsgsId).append('<div id="'+fieldErrorMessageId+'" class="error-message">'+options.prompt+'</div>');
                    }
                }

                // jump to top
                window.location.hash="topErrors";
                
                /*
                // add message near to field
                // there is no message yet
                if ($('#'+$(field).attr('id')+'+div.error-message').length==0)
                {
                    // add it
                    $(field).after('<div class="error-message">'+options.prompt+'</div>');
                }
                else
                {
                    // replace it
                    $('#'+$(field).attr('id')+'+div.error-message').html(options.prompt);
                }
                //}
                */
        }
        break;
    case 'wait':
        break;
    }
}
    

function formValidationAjax(params)
{
  var field = this;
  var url = params.url;
  
  delete params.url;
  params.value = $(field).val();

  // send request
  ajaxValidationCache($(field).attr('name')+'_'+params.value, function(callback){$.post (url, params, callback, 'json');},
                      function (data, text, status) {
                          if (data.error)
                          {
                              // notify validator about result
                              $.fn.formValidation.delayed.call (field, params,  "fail");
                              
                              // show message
                              if(data.message)
                              {
                                  formValidationNotify({field: field, status: 'fail', prompt: data.message});
                              }
                          }
                          else
                          {
                              // notify validator about result
                              $.fn.formValidation.delayed.call (field, params,  "pass");
                              if(data.message)
                              {
                                  formValidationNotify({field: field, status: 'pass', prompt: data.message});
                              }
                          }
                      }
      );
  
  return ("wait");
}


/**
 * implements cache for ajax validation requests
 * @param key key in cach which idetifies this request
 * @param ajaxFunc function which performes request, fuction should accept one
 * parameter -- callback it is function which it calls on request complete
 * @param callback fuction to call with results of request
 */
function ajaxValidationCache(key, ajaxFunc, callback)
{
    //ajaxValidationCache.cache; // assoc array, which holds results on requests
    if (typeof ajaxValidationCache.cache == 'undefined')
    {
        ajaxValidationCache.cache = {};
    }

    if (typeof ajaxValidationCache.cache[key] != 'undefined')
    {
        // timeout is necessary to give other code ability to work, so it is
        // full emulation of ajax call
        setTimeout(function(){ callback(ajaxValidationCache.cache[key].data, ajaxValidationCache.cache[key].text, ajaxValidationCache.cache[key].status); }, 30);
    }
    else
    {
        ajaxFunc(function(data, text, status){

                     // save result in cache
                     ajaxValidationCache.cache[key] = {data:data, text:text, status:status};
                     callback(data, text, status);
                 });
    }
}


/**
 * 3 seconds validation check
 */
function inactivityValidationTrigger(inputObj)
{
    this.inputObj = inputObj;
    this.timerId = null;

    this.startTimer = function()
    {
        this.timerId = setTimeout(function(){ inputObj.blur(); }, 3000);
    }

    this.stopTimer = function(){
        if (this.timerId)
        {
            clearTimeout(this.timerId);
        }
    }

    var self = this;
    
    inputObj.keydown(function(){self.stopTimer(); self.startTimer();});
}



/**
 * Validates that all given selects have value greater than 0 or both have value
 * equal to 0. That means iether both selected or both not selected
 * @param params object that contains key elementsIds it is array of ids of
 * validating elements with # at start
 */
function validateSeveralSelects(params)
{
    var fieldsCount = params.elementsIds.length;
    var selectedCount = 0;

    for(var i=0; i<fieldsCount; i++)
    {
        if ($(params.elementsIds[i]).val()>0)
        {
            selectedCount++;
        }
    }

    if (selectedCount==fieldsCount || selectedCount==0)
    {
        return 'pass';
    }
    else
    {
        return 'fail';
    }
}


function severalSelectsNotify(options)
{
    // by agreement div for error messages of form should have id formIdErrorMsgs
    var formErrorMsgsId = $(options.elementsIds[0]).closest('form').attr('id')+'ErrorMsgs';
    var fieldErrorMessageId = formErrorMsgsId+$(options.elementsIds[0]).attr('id');            // our error message div
    var fieldsCount = options.elementsIds.length;

    switch(options.status)
    {
    case 'pass':
        // remove error field highlights
        for( var i=0; i<fieldsCount; i++)
        {
            $(options.elementsIds[i]).removeClass('form-error');
            $(options.elementsIds[i]).addClass('field-valid');
        }
        
        //$('#'+$(field).attr('id')+'+div.error-message').remove();
        // remove message itself
        $('#'+fieldErrorMessageId).remove();
        break;
    case 'fail':

        // highlight fields
        for( var i=0; i<fieldsCount; i++)
        {
            $(options.elementsIds[i]).removeClass('field-valid');
            $(options.elementsIds[i]).addClass('form-error');
        }

        // show error message
        if(options.prompt)
        {
            // div containing error for message exists, insert message in it
            if($('#'+fieldErrorMessageId).length)
            {
                $('#'+fieldErrorMessageId).html(options.prompt); 
            }
            else
            {
                if (options.hightlightError)
                {
                    $('#'+formErrorMsgsId).append('<div id="'+fieldErrorMessageId+'" class="errorMessageHighlight">'+options.prompt+'</div>');
                }
                else
                {
                    $('#'+formErrorMsgsId).append('<div id="'+fieldErrorMessageId+'" class="error-message">'+options.prompt+'</div>');
                }
            }
        }

        // jump to top
        window.location.hash="topErrors";
        break;
    }
}


/**
 * Validates that at least one checkbox is checked
 * 
 */
function validateRequiredCheckboxes(params)
{
    if ($(params.containerId+' input:checkbox[checked]').length)
    {
        return 'pass';
    }
    else
    {
        return 'fail';
    }
}


function requiredCheckboxesNotify(params)
{
    var formErrorMsgsId = $(params.containerId).closest('form').attr('id')+'ErrorMsgs';
    var fieldErrorMessageId = formErrorMsgsId+$(params.containerId).attr('id');            // our error message div

    switch(params.status)
    {
    case 'pass':
        // remove error field highlights
        
        $(params.containerId).removeClass('form-error');
        $(params.containerId).addClass('field-valid');
        
        //$('#'+$(field).attr('id')+'+div.error-message').remove();
        // remove message itself
        $('#'+fieldErrorMessageId).remove();
        break;
    case 'fail':

        // highlight fields
        $(params.containerId).removeClass('field-valid');
        $(params.containerId).addClass('form-error');

        // show error message
        if(params.prompt)
        {
            // div containing error for message exists, insert message in it
            if($('#'+fieldErrorMessageId).length)
            {
                $('#'+fieldErrorMessageId).html(params.prompt); 
            }
            else
            {
                if (params.hightlightError)
                {
                    $('#'+formErrorMsgsId).append('<div id="'+fieldErrorMessageId+'" class="errorMessageHighlight">'+params.prompt+'</div>');
                }
                else
                {
                    $('#'+formErrorMsgsId).append('<div id="'+fieldErrorMessageId+'" class="error-message">'+params.prompt+'</div>');
                }
            }
        }
        
        // jump to top
        window.location.hash="topErrors";

        break;
    }
}

