var bmError = function() {

  var errorSummaryEmptyBlockTemplate = '<div id="errorSummary"><ol /></div>';
  var errorSummarySelector = '#errorSummary';
  var ctrlHolderErrorClass = 'error';

  function checkStatus(data, onError) {
    onError = $.isFunction(onError) ? onError : (function() {return false});
    switch (data.status) {
      case 'ok':
        return true;
        break;
      case 'fail':
        if (onError.apply(this, [data.content.message]) === false)
          alert(data.content.message);
        return false;
        break;
      case 'redirect':
        window.location = data.content.url;
        if ('force' in data.content)
          window.location.reload();
        return false;
        break;
    }
  }
  
  function handleHttpError(jqXHR, textStatus, errorThrown, onError)
  {
    onError = $.isFunction(onError) ? onError : (function() {return false});
    var msg = 'http status: ' + jqXHR.status + ' (' + textStatus + ')' + ', http error: ' + errorThrown;
    if (onError.apply(this, [msg]) === false)
      alert('Error: ' + msg);
  }

  function clearFormErrors(form) {
    $('p.errorField', form).remove();
    $('.error', form).removeClass('error');
    $(errorSummarySelector, form).remove();
  }

  function addErrorForForm(form, model, field, errors, showSummary)
  {
    if (typeof(showSummary) == 'undefined')
      showSummary = true;
    var summary = '';
    var input = $('[id$="' + model + '_' + field + '"]', form);
    var inputParent = input.parent().closest('div.ctrlHolder');
    if (inputParent.length > 0) {
      inputParent.addClass(ctrlHolderErrorClass);
      var errorId = form.attr('id') + field;
      for(var i = 0; i < errors.length; i++) {
        inputParent.prepend('<p id="error_' + errorId + '" class="errorField"><strong>' + errors[i] + '</strong></p>');
        if (showSummary)
          summary = summary + '<li><a href="#error_' + errorId + '">' + errors[i] + '</a></li>';
      }
    }
    else {
      for(var i = 0; i < errors.length; i++) {
        summary = summary + '<li>' + errors[i] + '</li>';
      }
    }
    if (showSummary) {
      var $errorSummaryElement = $(errorSummarySelector, form);
      if ($errorSummaryElement.length == 0) {
        form.prepend(errorSummaryEmptyBlockTemplate);
        $errorSummaryElement = $(errorSummarySelector, form);
      }
      $('ol', $errorSummaryElement).append(summary);
    }
  }

  function checkStatusForForm(form, data, showSummary) {
    clearFormErrors(form);
    return checkStatus(data, function(message) {
      var result = (typeof(message) === 'object');
      if (result) {
        for(var model in message) {
          for(var field in message[model]) {
            addErrorForForm(form, model, field, message[model][field], showSummary);
          }
        }
      }
      return result;
    });
  }

  return {
    checkStatus: checkStatus,
    checkStatusForForm: checkStatusForForm,
    addErrorForForm: addErrorForForm,
    clearFormErrors: clearFormErrors,
    handleHttpError: handleHttpError
  }

}();
