Source: dom/removeChild.js

// (c) Andrew Wei

'use strict';

import getChild from './getChild';
import getChildRegistry from './getChildRegistry';
import removeFromChildRegistry from './removeFromChildRegistry';
import assert from '../helpers/assert';
import assertType from '../helpers/assertType';
import noval from '../helpers/noval';

/**
 * Removes a child element(s) from an element.
 *
 * @param {Node} [element] - Specifies the parent Node to remove the child from.
 * @param {Node|Array|string} child - Child/children to be removed. This can be
 *                                    a Node or array. It can also be a string
 *                                    namespace of the target child/children.
 *
 * @alias module:requiem~dom.removeChild
 */
function removeChild() {
  assert((arguments.length > 0) && (arguments.length < 3), 'removeChild() expects either 1 or 2 arguments');

  let element = undefined;
  let child = undefined;

  if (arguments.length === 1) {
    child = arguments[0];
  }
  else {
    element = arguments[0];
    child = arguments[1];
  }

  assertType(element, Node, true, 'Parameter \'element\', if specified, must be a Node');

  let childRegistry = getChildRegistry(element);

  // If child is a string, treat each entry separated by '.' as a child name.
  if (typeof child === 'string') {
    return removeChild(element, getChild(element, child, true));
  }
  // If child is an array, remove each element inside recursively.
  else if ((child instanceof Array)) {
    let a = [];

    // 'child' here is a direct reference to the corresponding key in this
    // element's child registry.
    while (child.length > 0) {
      let c = removeChild(element, child[0]);
      if (c)
        a.push(c);
      else
        c.shift();
    }

    return a;
  }
  // If child is not an array, assume that it is an object that equates or
  // contains a valid DOM element. Remove it accordingly if this element
  // instance is indeed its parent/ancestor.
  else {
    // No valid DOM element found? Terminate.
    if (noval(child)) return null;

    removeFromChildRegistry(childRegistry, child);
    child.parentNode.removeChild(child);

    return child;
  }
}

export default removeChild;