@ngdoc directive
@name mdInputContainer
@module material.components.input

@restrict E

@description
`<md-input-container>` is the parent of any input or textarea element.

Input and textarea elements will not behave properly unless the md-input-container
parent is provided.

A single `<md-input-container>` should contain only one `<input>` element, otherwise it will throw an error.

<b>Exception:</b> Hidden inputs (`<input type="hidden" />`) are ignored and will not throw an error, so
you may combine these with other inputs.

<b>Note:</b> When using `ngMessages` with your input element, make sure the message and container elements
are *block* elements, otherwise animations applied to the messages will not look as intended. Either use a `div` and
apply the `ng-message` and `ng-messages` classes respectively, or use the `md-block` class on your element.

@param md-is-error {expression=} When the given expression evaluates to true, the input container
will go into error state. Defaults to erroring if the input has been touched and is invalid.
@param md-no-float {boolean=} When present, `placeholder` attributes on the input will not be converted to floating
labels.

@usage
<hljs lang="html">

<md-input-container>
<label>Username</label>
<input type="text" ng-model="user.name">
</md-input-container>

<md-input-container>
<label>Description</label>
<textarea ng-model="user.description"></textarea>
</md-input-container>

</hljs>

<h3>When disabling floating labels</h3>
<hljs lang="html">

<md-input-container md-no-float>
<input type="text" placeholder="Non-Floating Label">
</md-input-container>

</hljs>
function mdInputContainerDirective($mdTheming, $parse) {

  ContainerCtrl.$inject = ["$scope", "$element", "$attrs", "$animate"];
  var INPUT_TAGS = ['INPUT', 'TEXTAREA', 'SELECT', 'MD-SELECT'];

  var LEFT_SELECTORS = INPUT_TAGS.reduce(function(selectors, isel) {
    return selectors.concat(['md-icon ~ ' + isel, '.md-icon ~ ' + isel]);
  }, []).join(",");

  var RIGHT_SELECTORS = INPUT_TAGS.reduce(function(selectors, isel) {
    return selectors.concat([isel + ' ~ md-icon', isel + ' ~ .md-icon']);
  }, []).join(",");

  return {
    restrict: 'E',
    compile: compile,
    controller: ContainerCtrl
  };

  function compile(tElement) {
    // Check for both a left & right icon
    var leftIcon = tElement[0].querySelector(LEFT_SELECTORS);
    var rightIcon = tElement[0].querySelector(RIGHT_SELECTORS);

    if (leftIcon) { tElement.addClass('md-icon-left'); }
    if (rightIcon) { tElement.addClass('md-icon-right'); }

    return function postLink(scope, element) {
      $mdTheming(element);
    };
  }

  function ContainerCtrl($scope, $element, $attrs, $animate) {
    var self = this;

    self.isErrorGetter = $attrs.mdIsError && $parse($attrs.mdIsError);

    self.delegateClick = function() {
      self.input.focus();
    };
    self.element = $element;
    self.setFocused = function(isFocused) {
      $element.toggleClass('md-input-focused', !!isFocused);
    };
    self.setHasValue = function(hasValue) {
      $element.toggleClass('md-input-has-value', !!hasValue);
    };
    self.setHasPlaceholder = function(hasPlaceholder) {
      $element.toggleClass('md-input-has-placeholder', !!hasPlaceholder);
    };
    self.setInvalid = function(isInvalid) {
      if (isInvalid) {
        $animate.addClass($element, 'md-input-invalid');
      } else {
        $animate.removeClass($element, 'md-input-invalid');
      }
    };
    $scope.$watch(function() {
      return self.label && self.input;
    }, function(hasLabelAndInput) {
      if (hasLabelAndInput && !self.label.attr('for')) {
        self.label.attr('for', self.input.attr('id'));
      }
    });
  }
}