<script>
function DOMAgent(delegate) {
  this.enabled = false;
  this.delegate_ = delegate;
  this.nextNodeId_ = 1;
  this.nodeToId_ = new Map();
  this.idToNode_ = new Map();
}

DOMAgent.prototype.getIdForNode_ = function(node) {
  if (this.nodeToId_.has(node))
    return this.nodeToId_.get(node);
  var id = this.nextNodeId_++;
  this.nodeToId_.set(node, id);
  this.idToNode_.set(id, node);
  return id;
};

DOMAgent.prototype.getNodeForId = function(nodeId) {
  return this.idToNode_.get(nodeId);
};

DOMAgent.prototype.serializeChildren_ = function(node) {
  var children = [];
  for (var child = node.firstChild; child; child = child.nextSibling) {
    var record = this.serializeNode_(child);
    if (record)
      children.push(record);
  }
  return children;
};

DOMAgent.prototype.serializeAttributes_ = function(element) {
  var attributes = [];
  var attrs = element.getAttributes();
  for (var i = 0; i < attrs.length; ++i) {
    var attr = attrs[i];
    attributes.push(attr.name);
    attributes.push(attr.value);
  }
  return attributes;
};

DOMAgent.prototype.serializeNode_ = function(node) {
  var id = this.getIdForNode_(node);

  var record = {
    nodeId: id,
  };

  var isContainer = false;

  if (node instanceof Element) {
    isContainer = true;
    record.nodeType = 1;
    record.nodeName = node.tagName;
    record.localName = node.tagName;
    record.nodeValue = "";
    record.attributes = this.serializeAttributes_(node);
  } else if (node instanceof Text) {
    record.nodeType = 3;
    record.nodeName = "#text";
    var nodeValue = node.data;
    if (!nodeValue.trim())
      return null;
    record.nodeValue = nodeValue;
  } else if (node instanceof Document) {
    isContainer = true;
    record.nodeType = 9;
    record.nodeName = "#document";
    record.localName = "";
    record.nodeValue = "";
    record.documentURL = node.URL;
    record.baseURL = node.baseURI;
  } else if (node instanceof DocumentFragment) {
    isContainer = true;
    record.nodeType = 11;
    record.nodeName = "#document-fragment";
    record.localName = "";
    record.nodeValue = "";
  } else {
    console.log("Unknown node type");
    return null;
  }

  if (isContainer) {
    var children = this.serializeChildren_(node);
    if (children.length) {
      record.childNodeCount = children.length;
      record.children = children;
    }
  }

  return record;
};

DOMAgent.prototype.enable = function() {
  this.enabled = true;
  this.observer_ = new MutationObserver(this.mutationCallback_.bind(this));
  this.observer_.observe(document, {
    childList: true,
    attributes: true,
    characterData: true,
    subtree : true,
  });
};

DOMAgent.prototype.getDocument = function() {
  return {
    root: this.serializeNode_(document),
  };
};

DOMAgent.prototype.hideHighlight = function() {
};

DOMAgent.prototype.highlightNode = function() {
};

DOMAgent.prototype.mutationCallback_ = function(mutationRecords) {
  for (var i = 0; i < mutationRecords.length; ++i) {
    var record = mutationRecords[i];
    var type = record.type;
    var target = record.target;
    var nodeId = this.getIdForNode_(target);
    if (type == "attributes") {
      var attributeName = record.attributeName;
      if (target.hasAttribute(attributeName)) {
        this.delegate_.sendMessage("DOM.attributeModified", {
          nodeId: nodeId,
          name: attributeName,
          value: target.getAttribute(attributeName),
        });
      } else {
        this.delegate_.sendMessage("DOM.attributeRemoved", {
          nodeId: nodeId,
          name: attributeName,
        });
      }
    } else if (type == "characterData") {
      this.delegate_.sendMessage("DOM.characterDataModified", {
        nodeId: nodeId,
        characterData: target.data,
      });
    } else if (type == "childList") {
      // FIXME: If this subtree isn't expanded, we only need to send across the
      // {"method":"DOM.childNodeCountUpdated","params":"nodeId":648,"childNodeCount":2}

      Array.prototype.forEach.call(record.removedNodes, function(node) {
        this.delegate_.sendMessage("DOM.childNodeRemoved", {
          parentNodeId: nodeId,
          nodeId: this.getIdForNode_(node),
        });
      }.bind(this));

      Array.prototype.forEach.call(record.addedNodes, function(node) {
        var previousNodeId = node.previousSibling ? this.getIdForNode_(node.previousSibling) : 0;
        this.delegate_.sendMessage("DOM.childNodeInserted", {
          parentNodeId: nodeId,
          previousNodeId: previousNodeId,
          node: this.serializeNode_(node),
        });
      }.bind(this));
    }
  }
};

module.exports = DOMAgent;
</script>
