// Copyright 2016 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// JavaScript functions used by the Chrome debugging protocol DOM domain:
// https://chromedevtools.github.io/devtools-protocol/1-3/DOM

devtoolsBackend.dom = {};

// Alias to match the uppercase domain of the devtools protocol.
devtoolsBackend.DOM = devtoolsBackend.dom;

// Creates and returns a new Node object corresponding to the document node,
// including its children up to a default depth.
// https://chromedevtools.github.io/devtools-protocol/1-3/DOM#method-getDocument
devtoolsBackend.dom.getDocument = function(params) {
  var result = {};
  result.root = this.getNodeWithChildren(document, 2);
  result.root.documentURL = document.URL;
  return JSON.stringify(result);
}

// Creates an array of Node objects corresponding to the children of the
// specified node, and returns them via an event. A depth may be specified,
// where a negative depth means to return all descendants. If no depth is
// specified, the default is 1, a single level.
// https://chromedevtools.github.io/devtools-protocol/1-3/DOM#method-requestChildNodes
devtoolsBackend.dom.requestChildNodes = function(params) {
  var node = this.findNode(params);
  var depth = params.depth || 1;
  var result = {};
  result.parentId = params.nodeId;
  result.nodes = this.getChildNodes(node, depth);

  // Send the result via an event, and an empty response.
  devtoolsBackend.sendEvent('DOM.setChildNodes', JSON.stringify(result));
  return '{}';
}

// Finds the node corresponding to a remote objectId. Also sends all nodes on
// the path from the requested one to the root as a series of setChildNodes
// events.
// https://chromedevtools.github.io/devtools-protocol/1-3/DOM#method-requestNode
devtoolsBackend.dom.requestNode = function(params) {
  var node = this.findNode(params);
  var nodeInfo = new this.Node(node);
  var result = {};
  result.nodeId = nodeInfo.nodeId;

  var parent = node.parentNode;
  while (parent) {
    var parentInfo = new this.Node(parent);
    var params = {};
    params.parentId = parentInfo.nodeId;
    params.nodes = [];
    params.nodes.push(nodeInfo);
    devtoolsBackend.sendEvent('DOM.setChildNodes', JSON.stringify(params));
    node = parent;
    nodeInfo = parentInfo;
    parent = parent.parentNode;
  }

  return JSON.stringify(result);
}

// Returns a Runtime.RemoteObject corresponding to a node.
// https://chromedevtools.github.io/devtools-protocol/1-3/DOM#method-resolveNode
devtoolsBackend.dom.resolveNode = function(params) {
  var node = this.findNode(params);
  var returnByValue = true;
  var result = {};
  result.object = new devtoolsBackend.runtime.RemoteObject(
        node, params.objectGroup, returnByValue);

  return JSON.stringify(result);
}

// Returns the bounding box of a node. Used for node highlighting.
devtoolsBackend.dom.getBoundingClientRect = function(params) {
  var node = this.findNode(params);
  return JSON.stringify(node.getBoundingClientRect());
}

// Creates and returns a Node object that represents the specified node.
// Adds the node's children up to the specified depth. A negative depth will
// cause all descendants to be added.
devtoolsBackend.dom.getNodeWithChildren = function(node, depth) {
  var result = new this.Node(node);
  if (depth != 0) {
    result.children = this.getChildNodes(node, depth);
  }
  return result;
}

// Creates and returns an array of Node objects corresponding to the children
// of the specified node, recursing on each on up to the specified depth.
devtoolsBackend.dom.getChildNodes = function(node, depth) {
  if (!node.childNodes) {
    return [];
  }

  var children = [];
  for (var i = 0; i < node.childNodes.length; i++) {
    var child = node.childNodes[i];
    if (!this.nodeIsIgnorable(child)) {
      children.push(this.getNodeWithChildren(child, depth - 1));
    }
  }
  return children;
}

// Finds a node specified by either nodeId or objectId (to get a node
// from its corresponding remote object).
devtoolsBackend.dom.findNode = function(params) {
  if (params.nodeId != null) {
    return this.nodeStore[params.nodeId];
  }

  if (params.objectId != null) {
    return devtoolsBackend.runtime.getObject(params.objectId);
  }

  // Either nodeId or objectId must be specified.
  return null;
}

// Adds a node to the internal node store and returns a unique id that can
// be used to access it again.
devtoolsBackend.dom.addNode = function(node) {
  // If we've already added this node, then use the same nodeId.
  for (var i = 0; i < this.nodeStore.length; i++) {
    if (this.nodeStore[i] === node) {
      return i;
    }
  }

  var nodeId = this.nextNodeId++;
  this.nodeStore[nodeId] = node;
  return nodeId;
}

// Whether a node is ignorable. We ignore text nodes with white-space only
// content, as they just clutter up the DOM tree.
devtoolsBackend.dom.nodeIsIgnorable = function(node) {
  return node.nodeType == Node.TEXT_NODE &&
      !(/[^\t\n\r ]/.test(node.textContent));
}

// Creates a new Node object, which is the type used to return information
// about nodes to devtools. All Node objects are added to |nodeStore|,
// so they can be retrieved later via |nodeId|.
devtoolsBackend.dom.Node = function(node) {
  this.nodeId = devtoolsBackend.dom.addNode(node);
  this.localName = node.nodeName;
  this.nodeName = node.nodeName;
  this.nodeType = node.nodeType;
  this.nodeValue = node.nodeValue || "";
  this.childNodeCount = node.childNodes.length;

  if (node.attributes) {
    this.attributes = [];
    for (var i = 0; i < node.attributes.length; i++) {
      this.attributes.push(node.attributes[i].name);
      this.attributes.push(node.attributes[i].value);
    }
  }
}

devtoolsBackend.dom.nodeStore = [];
devtoolsBackend.dom.nextNodeId = 0;
