text: "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  require("./types");
  const attr_1 = require("./attr");
  const cdata_section_1 = require("./cdata-section");
  const comment_1 = require("./comment");
  const document_fragment_1 = require("./document-fragment");
  const document_utils_1 = require("./document-utils");
  const dummy_document_1 = require("./dummy/dummy-document");
  const element_1 = require("./element");
  const entity_reference_1 = require("./entity-reference");
  const live_node_list_1 = require("./live-node-list");
  const named_node_map_1 = require("./named-node-map");
  const node_list_1 = require("./node-list");
  const node_list_of_1 = require("./node-list-of");
  const node_types_1 = require("./node-types");
  const processing_instruction_1 = require("./processing-instruction");
  const text_1 = require("./text");
  const utils_1 = require("./utils");
  class DocumentImpl extends dummy_document_1.DummyDocument {
      constructor() {
          super();
          this.doctype = null;
          this.documentElement = null;
          this._inc = 1;
          this.nodeName = '#document';
          this.nodeType = node_types_1.NodeTypeTS.DOCUMENT_NODE;
      }
      insertBefore(newChild, refChild) {
          // raises
          if (utils_1.isDocumentFragment(newChild)) {
              let child = newChild.firstChild;
              while (child) {
                  const next = child.nextSibling;
                  this.insertBefore(child, refChild);
                  child = next;
              }
              return newChild;
          }
          else {
              if (this.documentElement == null && utils_1.isElement(newChild)) {
                  this.documentElement = utils_1.asHTMLElement(newChild);
              }
              const _newChild = document_utils_1._insertBefore(this, utils_1.asChildNode(newChild), refChild == null ? null : utils_1.asChildNode(refChild));
              utils_1.asChildNode(newChild).ownerDocument = this;
              // notify observers
              this.queueMutation({
                  type: 'childList',
                  target: this,
                  addedNodes: new node_list_1.NodeListImpl(_newChild),
                  removedNodes: new node_list_1.NodeListImpl(),
                  previousSibling: _newChild.previousSibling,
                  nextSibling: _newChild.nextSibling,
                  attributeName: null,
                  attributeNamespace: null,
                  oldValue: null,
              });
              return _newChild;
          }
      }
      removeChild(oldChild) {
          if (this.documentElement === oldChild) {
              this.documentElement = null;
          }
          return document_utils_1._removeChild(this, oldChild);
      }
      // Introduced in DOM Level 2:
      importNode(importedNode, deep) {
          return document_utils_1.importNode(this, importedNode, deep);
      }
      // Introduced in DOM Level 2:
      getElementById(id) {
          let rtv = null;
          document_utils_1._visitNode(this.documentElement, (node) => {
              if (utils_1.isElement(node)) {
                  if (node.getAttribute('id') === id) {
                      rtv = node;
                      return true;
                  }
              }
          });
          return rtv;
      }
      getElementsByTagName(tagName) {
          return new live_node_list_1.LiveNodeListImpl(this, (base) => {
              const ls = [];
              document_utils_1._visitNode(base, (node) => {
                  if (node !== base && utils_1.isElement(node) && (tagName === '*' || node.tagName === tagName)) {
                      ls.push(node);
                  }
              });
              return ls;
          });
      }
      getElementsByTagNameNS(namespaceURI, localName) {
          return new live_node_list_1.LiveNodeListImpl(this, (base) => {
              const ls = [];
              document_utils_1._visitNode(base, (node) => {
                  if (node !== base &&
                      utils_1.isElement(node) &&
                      (namespaceURI === '*' || node.namespaceURI === namespaceURI) &&
                      (localName === '*' || node.localName === localName)) {
                      ls.push(node);
                  }
              });
              return ls;
          });
      }
      // document factory method:
      createElement(tagName) {
          const node = new element_1.ElementImpl();
          node.ownerDocument = this;
          node.nodeName = tagName;
          node.tagName = tagName;
          node.childNodes = new node_list_of_1.NodeListOfImpl();
          const attrs = (node.attributes = new named_node_map_1.NamedNodeMapImpl());
          attrs._ownerElement = node;
          return node;
      }
      createDocumentFragment() {
          const node = new document_fragment_1.DocumentFragmentImpl();
          node.ownerDocument = this;
          node.childNodes = new node_list_of_1.NodeListOfImpl();
          return node;
      }
      createTextNode(data) {
          const node = new text_1.TextImpl();
          node.ownerDocument = this;
          node.appendData(data);
          return node;
      }
      createComment(data) {
          const node = new comment_1.CommentImpl();
          node.ownerDocument = this;
          node.appendData(data);
          return node;
      }
      createCDATASection(data) {
          const node = new cdata_section_1.CDATASectionImpl();
          node.ownerDocument = this;
          node.appendData(data);
          return node;
      }
      createProcessingInstruction(target, data) {
          const node = new processing_instruction_1.ProcessingInstructionImpl();
          node.ownerDocument = this;
          node.tagName = node.target = target;
          node.nodeValue = node.data = data;
          return node;
      }
      createAttribute(name) {
          const node = new attr_1.AttrImpl();
          node.ownerDocument = this;
          node.name = name;
          node.nodeName = name;
          node.localName = name;
          node.specified = true;
          return node;
      }
      createEntityReference(name) {
          const node = new entity_reference_1.EntityReferenceImpl();
          node.ownerDocument = this;
          node.nodeName = name;
          return node;
      }
      // Introduced in DOM Level 2:
      createElementNS(namespaceURI, qualifiedName) {
          const node = new element_1.ElementImpl();
          const pl = qualifiedName.split(':');
          const attrs = (node.attributes = new named_node_map_1.NamedNodeMapImpl());
          node.childNodes = new node_list_of_1.NodeListOfImpl();
          node.ownerDocument = this;
          node.nodeName = qualifiedName;
          node.tagName = qualifiedName;
          node.namespaceURI = namespaceURI;
          if (pl.length === 2) {
              node.prefix = pl[0];
              node.localName = pl[1];
          }
          else {
              // el.prefix = null;
              node.localName = qualifiedName;
          }
          attrs._ownerElement = node;
          return node;
      }
      // Introduced in DOM Level 2:
      createAttributeNS(namespaceURI, qualifiedName) {
          const node = new attr_1.AttrImpl();
          const pl = qualifiedName.split(':');
          node.ownerDocument = this;
          node.nodeName = qualifiedName;
          node.name = qualifiedName;
          node.namespaceURI = namespaceURI;
          node.specified = true;
          if (pl.length === 2) {
              node.prefix = pl[0];
              node.localName = pl[1];
          }
          else {
              // el.prefix = null;
              node.localName = qualifiedName;
          }
          return node;
      }
  }
  exports.DocumentImpl = DocumentImpl;
  //# sourceMappingURL=document.js.map