// 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://developer.chrome.com/devtools/docs/protocol/1.1/dom

devtoolsBackend.dom = {};

// Creates and returns a new Node object corresponding to the document node,
// including its children up to a default depth.
// https://developer.chrome.com/devtools/docs/protocol/1.1/dom#command-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://developer.chrome.com/devtools/docs/protocol/1.1/dom#command-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://developer.chrome.com/devtools/docs/protocol/1.1/dom#command-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://developer.chrome.com/devtools/docs/protocol/1.1/dom#command-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;