/**
 * Utility methods used for displaying error messages (attached to $.formUtils)
 */
(function ($) {

  'use strict';

  var dialogs = {

    resolveErrorMessage: function($elem, validator, validatorName, conf, language) {
      var errorMsgAttr = conf.validationErrorMsgAttribute + '-' + validatorName.replace('validate_', ''),
        validationErrorMsg = $elem.attr(errorMsgAttr);

      if (!validationErrorMsg) {
        validationErrorMsg = $elem.attr(conf.validationErrorMsgAttribute);
        if (!validationErrorMsg) {
          if (typeof validator.errorMessageKey !== 'function') {
            validationErrorMsg = language[validator.errorMessageKey];
          }
          else {
            validationErrorMsg = language[validator.errorMessageKey(conf)];
          }
          if (!validationErrorMsg) {
            validationErrorMsg = validator.errorMessage;
          }
        }
      }
      return validationErrorMsg;
    },
    getParentContainer: function ($elem) {
      if ($elem.valAttr('error-msg-container')) {
        return $($elem.valAttr('error-msg-container'));
      } else {
        var $parent = $elem.parent();
        if (!$parent.hasClass('form-group') && !$parent.closest('form').hasClass('form-horizontal')) {
          var $formGroup = $parent.closest('.form-group');
          if ($formGroup.length) {
            return $formGroup.eq(0);
          }
        }
        return $parent;
      }
    },
    applyInputErrorStyling: function ($input, conf) {
      $input
        .addClass(conf.errorElementClass)
        .removeClass(conf.successElementClass);

      this.getParentContainer($input)
        .addClass(conf.inputParentClassOnError)
        .removeClass(conf.inputParentClassOnSuccess);

      if (conf.borderColorOnError !== '') {
        $input.css('border-color', conf.borderColorOnError);
      }
    },
    applyInputSuccessStyling: function($input, conf) {
      $input.addClass(conf.successElementClass);
      this.getParentContainer($input)
        .addClass(conf.inputParentClassOnSuccess);
    },
    removeInputStylingAndMessage: function($input, conf) {

      // Reset input css
      $input
        .removeClass(conf.successElementClass)
        .removeClass(conf.errorElementClass)
        .css('border-color', '');

      var $parentContainer = dialogs.getParentContainer($input);

      // Reset parent css
      $parentContainer
        .removeClass(conf.inputParentClassOnError)
        .removeClass(conf.inputParentClassOnSuccess);

      // Remove possible error message
      if (typeof conf.inlineErrorMessageCallback === 'function') {
        var $errorMessage = conf.inlineErrorMessageCallback($input, false, conf);
        if ($errorMessage) {
          $errorMessage.html('');
        }
      } else {
        $parentContainer
          .find('.' + conf.errorMessageClass)
          .remove();
      }

    },
    removeAllMessagesAndStyling: function($form, conf) {

      // Remove error messages in top of form
      if (typeof conf.submitErrorMessageCallback === 'function') {
        var $errorMessagesInTopOfForm = conf.submitErrorMessageCallback($form, false, conf);
        if ($errorMessagesInTopOfForm) {
          $errorMessagesInTopOfForm.html('');
        }
      } else {
        $form.find('.' + conf.errorMessageClass + '.alert').remove();
      }

      // Remove input css/messages
      $form.find('.' + conf.errorElementClass + ',.' + conf.successElementClass).each(function() {
        dialogs.removeInputStylingAndMessage($(this), conf);
      });
    },
    setInlineMessage: function ($input, errorMsg, conf) {

      this.applyInputErrorStyling($input, conf);

      var custom = document.getElementById($input.attr('name') + '_err_msg'),
        $messageContainer = false,
        setErrorMessage = function ($elem) {
          $.formUtils.$win.trigger('validationErrorDisplay', [$input, $elem]);
          $elem.html(errorMsg);
        },
        addErrorToMessageContainer = function() {
          var $found = false;
          $messageContainer.find('.' + conf.errorMessageClass).each(function () {
            if (this.inputReferer === $input[0]) {
              $found = $(this);
              return false;
            }
          });
          if ($found) {
            if (!errorMsg) {
              $found.remove();
            } else {
              setErrorMessage($found);
            }
          } else if(errorMsg !== '') {
            $message = $('<div class="' + conf.errorMessageClass + ' alert"></div>');
            setErrorMessage($message);
            $message[0].inputReferer = $input[0];
            $messageContainer.prepend($message);
          }
        },
        $message;

      if (custom) {
        // Todo: remove in 3.0
        $.formUtils.warn('Using deprecated element reference ' + custom.id);
        $messageContainer = $(custom);
        addErrorToMessageContainer();
      } else if (typeof conf.inlineErrorMessageCallback === 'function') {
        $messageContainer = conf.inlineErrorMessageCallback($input, errorMsg, conf);
        if (!$messageContainer) {
          // Error display taken care of by inlineErrorMessageCallback
          return;
        }
        addErrorToMessageContainer();
      } else {
        var $parent = this.getParentContainer($input);
        $message = $parent.find('.' + conf.errorMessageClass + '.help-block');
        if ($message.length === 0) {
          $message = $('<span></span>').addClass('help-block').addClass(conf.errorMessageClass);
          $message.appendTo($parent);
        }
        setErrorMessage($message);
      }
    },
    setMessageInTopOfForm: function ($form, errorMessages, conf, lang) {
      var view = '<div class="{errorMessageClass} alert alert-danger">'+
                    '<strong>{errorTitle}</strong>'+
                    '<ul>{fields}</ul>'+
                '</div>',
          $container = false;

      if (typeof conf.submitErrorMessageCallback === 'function') {
        $container = conf.submitErrorMessageCallback($form, errorMessages, conf);
        if (!$container) {
          // message display taken care of by callback
          return;
        }
      }

      var viewParams = {
            errorTitle: lang.errorTitle,
            fields: '',
            errorMessageClass: conf.errorMessageClass
          };

      $.each(errorMessages, function (i, msg) {
        viewParams.fields += '<li>'+msg+'</li>';
      });

      $.each(viewParams, function(param, value) {
        view = view.replace('{'+param+'}', value);
      });

      if ($container) {
        $container.html(view);
      } else {
        $form.children().eq(0).before($(view));
      }
    }
  };

  $.formUtils = $.extend($.formUtils || {}, {
    dialogs: dialogs
  });

})(jQuery);
