function ngMessageDirectiveFactory(isDefault) {
  return ['$animate', function($animate) {
    return {
      restrict: 'AE',
      transclude: 'element',
      priority: 1, // must run before ngBind, otherwise the text is set on the comment
      terminal: true,
      require: '^^ngMessages',
      link: function(scope, element, attrs, ngMessagesCtrl, $transclude) {
        var commentNode, records, staticExp, dynamicExp;

        if (!isDefault) {
          commentNode = element[0];
          staticExp = attrs.ngMessage || attrs.when;
          dynamicExp = attrs.ngMessageExp || attrs.whenExp;

          var assignRecords = function(items) {
            records = items
                ? (isArray(items)
                      ? items
                      : items.split(/[\s,]+/))
                : null;
            ngMessagesCtrl.reRender();
          };

          if (dynamicExp) {
            assignRecords(scope.$eval(dynamicExp));
            scope.$watchCollection(dynamicExp, assignRecords);
          } else {
            assignRecords(staticExp);
          }
        }

        var currentElement, messageCtrl;
        ngMessagesCtrl.register(commentNode, messageCtrl = {
          test: function(name) {
            return contains(records, name);
          },
          attach: function() {
            if (!currentElement) {
              $transclude(function(elm, newScope) {
                $animate.enter(elm, null, element);
                currentElement = elm;

                // Each time we attach this node to a message we get a new id that we can match
                // when we are destroying the node later.
                var $$attachId = currentElement.$$attachId = ngMessagesCtrl.getAttachId();

                // in the event that the element or a parent element is destroyed
                // by another structural directive then it's time
                // to deregister the message from the controller
                currentElement.on('$destroy', function() {
                  // If the message element was removed via a call to `detach` then `currentElement` will be null
                  // So this handler only handles cases where something else removed the message element.
                  if (currentElement && currentElement.$$attachId === $$attachId) {
                    ngMessagesCtrl.deregister(commentNode, isDefault);
                    messageCtrl.detach();
                  }
                  newScope.$destroy();
                });
              });
            }
          },
          detach: function() {
            if (currentElement) {
              var elm = currentElement;
              currentElement = null;
              $animate.leave(elm);
            }
          }
        }, isDefault);

        // We need to ensure that this directive deregisters itself when it no longer exists
        // Normally this is done when the attached element is destroyed; but if this directive
        // gets removed before we attach the message to the DOM there is nothing to watch
        // in which case we must deregister when the containing scope is destroyed.
        scope.$on('$destroy', function() {
          ngMessagesCtrl.deregister(commentNode, isDefault);
        });
      }
    };
  }];

  function contains(collection, key) {
    if (collection) {
      return isArray(collection)
          ? collection.indexOf(key) >= 0
          : collection.hasOwnProperty(key);
    }
  }
}
@ngdoc directive
@name ngMessageDefault
@restrict AE
@scope

@description
`ngMessageDefault` is a directive with the purpose to show and hide a default message for
{@link directive:ngMessages}, when none of provided messages matches.

More information about using `ngMessageDefault` can be found in the
{@link module:ngMessages `ngMessages` module documentation}.

@usage
```html
<!-- using attribute directives -->
<ANY ng-messages="expression" role="alert">
  <ANY ng-message="stringValue">...</ANY>
  <ANY ng-message="stringValue1, stringValue2, ...">...</ANY>
  <ANY ng-message-default>...</ANY>
</ANY>

<!-- or by using element directives -->
<ng-messages for="expression" role="alert">
  <ng-message when="stringValue">...</ng-message>
  <ng-message when="stringValue1, stringValue2, ...">...</ng-message>
  <ng-message-default>...</ng-message-default>
</ng-messages>