function normalizeClass(component, attrs, streamBasePath) {
  let normalizedClass = [];
  let classNames = get(component, 'classNames');
  let classNameBindings = get(component, 'classNameBindings');

  if (attrs.class) {
    if (isStream(attrs.class)) {
      normalizedClass.push(buildStatement('subexpr', '-normalize-class', [buildStatement('value', attrs.class.path), buildStatement('value', attrs.class)], []));
    } else {
      normalizedClass.push(attrs.class);
    }
  }

  if (attrs.classBinding) {
    normalizeClasses(attrs.classBinding.split(' '), normalizedClass, streamBasePath);
  }

  if (classNames) {
    for (let i = 0; i < classNames.length; i++) {
      normalizedClass.push(classNames[i]);
    }
  }

  if (classNameBindings) {
    normalizeClasses(classNameBindings, normalizedClass, streamBasePath);
  }

  if (normalizeClass.length) {
    return buildStatement('subexpr', '-join-classes', normalizedClass, []);
  }
}
function normalizeClasses(classes, output, streamBasePath) {
  for (let i = 0; i < classes.length; i++) {
    let className = classes[i];
    assert('classNameBindings must not have spaces in them. Multiple class name bindings can be provided as elements of an array, e.g. [\'foo\', \':bar\']', className.indexOf(' ') === -1);

    let [propName, activeClass, inactiveClass] = className.split(':');

    // Legacy :class microsyntax for static class names
    if (propName === '') {
      output.push(activeClass);
      continue;
    }

    let prop = `${streamBasePath}${propName}`;

    output.push(buildStatement('subexpr', '-normalize-class', [
      // params
      buildStatement('value', propName),
      buildStatement('get', prop)
    ], [
      // hash
      'activeClass', activeClass,
      'inactiveClass', inactiveClass
    ]));
  }
}
export function buildHTMLTemplate(tagName, _attrs, content) {
  let attrs = {};

  for (let prop in _attrs) {
    let val = _attrs[prop];

    if (typeof val === 'string') {
      attrs[prop] = val;
    } else {
      attrs[prop] = buildStatement('value', val);
    }
  }

  let childTemplate = content.templates.default;
  let elementTemplate = internal.manualElement(tagName, attrs, childTemplate.isEmpty);

  if (childTemplate.isEmpty) {
    return blockFor(elementTemplate, { scope: content.scope });
  } else {
    let blockToRender = blockFor(content.templates.default, content);
    return blockFor(elementTemplate, { yieldTo: blockToRender, scope: content.scope });
  }
}
// Takes a component and builds a normalized set of attribute
// bindings consumable by HTMLBars' `attribute` hook.
function normalizeComponentAttributes(component, attrs) {
  let normalized = {};
  let attributeBindings = component.attributeBindings;
  let streamBasePath = component.isComponent ? '' : 'view.';

  if (attrs.id && getValue(attrs.id)) {
    // Do not allow binding to the `id`
    normalized.id = getValue(attrs.id);
    component.elementId = normalized.id;
  } else {
    normalized.id = component.elementId;
  }

  if (attributeBindings) {
    for (let i = 0; i < attributeBindings.length; i++) {
      let attr = attributeBindings[i];
      let colonIndex = attr.indexOf(':');

      let attrName, expression;
      if (colonIndex !== -1) {
        let attrProperty = attr.substring(0, colonIndex);
        attrName = attr.substring(colonIndex + 1);
        expression = buildStatement('get', `${streamBasePath}${attrProperty}`);
      } else if (attrs[attr]) {
        // TODO: For compatibility with 1.x, we probably need to `set`
        // the component's attribute here if it is a CP, but we also
        // probably want to suspend observers and allow the
        // willUpdateAttrs logic to trigger observers at the correct time.
        attrName = attr;
        expression = buildStatement('value', attrs[attr]);
      } else {
        attrName = attr;
        expression = buildStatement('get', `${streamBasePath}${attr}`);
      }

      assert('You cannot use class as an attributeBinding, use classNameBindings instead.', attrName !== 'class');
      normalized[attrName] = expression;
    }
  }

  if (attrs.tagName) {
    component.tagName = attrs.tagName;
  }

  let normalizedClass = normalizeClass(component, attrs, streamBasePath);
  if (normalizedClass) {
    normalized.class = normalizedClass;
  }

  if (get(component, 'isVisible') === false) {
    let hiddenStyle = buildStatement('subexpr', '-html-safe', ['display: none;'], []);
    let existingStyle = normalized.style;

    if (existingStyle) {
      normalized.style = buildStatement('subexpr', 'concat', [existingStyle, ' ', hiddenStyle], [ ]);
    } else {
      normalized.style = hiddenStyle;
    }
  }

  return normalized;
}