// 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.

#include "cobalt/debug/dom_component.h"

#include <string>

#include "base/bind.h"
#include "cobalt/math/matrix3_f.h"
#include "cobalt/math/transform_2d.h"
#include "cobalt/render_tree/brush.h"
#include "cobalt/render_tree/color_rgba.h"
#include "cobalt/render_tree/rect_node.h"

namespace cobalt {
namespace debug {

namespace {
// File to load JavaScript DOM debugging domain implementation from.
const char kScriptFile[] = "dom.js";

// Command "methods" (names) from the set specified here:
// https://developer.chrome.com/devtools/docs/protocol/1.1/dom
const char kDisable[] = "DOM.disable";
const char kEnable[] = "DOM.enable";
const char kGetDocument[] = "DOM.getDocument";
const char kRequestChildNodes[] = "DOM.requestChildNodes";
const char kRequestNode[] = "DOM.requestNode";
const char kResolveNode[] = "DOM.resolveNode";
const char kHideHighlight[] = "DOM.hideHighlight";
const char kHighlightNode[] = "DOM.highlightNode";

// Parameter names:
const char kA[] = "a";
const char kB[] = "b";
const char kContentColor[] = "contentColor";
const char kG[] = "g";
const char kHighlightConfig[] = "highlightConfig";
const char kR[] = "r";
}  // namespace

DOMComponent::DOMComponent(ComponentConnector* connector,
                           scoped_ptr<RenderLayer> render_layer)
    : connector_(connector), render_layer_(render_layer.Pass()) {
  DCHECK(connector_);
  connector_->AddCommand(
      kDisable, base::Bind(&DOMComponent::Disable, base::Unretained(this)));
  connector_->AddCommand(
      kEnable, base::Bind(&DOMComponent::Enable, base::Unretained(this)));
  connector_->AddCommand(kGetDocument, base::Bind(&DOMComponent::GetDocument,
                                                  base::Unretained(this)));
  connector_->AddCommand(
      kRequestChildNodes,
      base::Bind(&DOMComponent::RequestChildNodes, base::Unretained(this)));
  connector_->AddCommand(kRequestNode, base::Bind(&DOMComponent::RequestNode,
                                                  base::Unretained(this)));
  connector_->AddCommand(kResolveNode, base::Bind(&DOMComponent::ResolveNode,
                                                  base::Unretained(this)));
  connector_->AddCommand(
      kHighlightNode,
      base::Bind(&DOMComponent::HighlightNode, base::Unretained(this)));
  connector_->AddCommand(
      kHideHighlight,
      base::Bind(&DOMComponent::HideHighlight, base::Unretained(this)));
}

JSONObject DOMComponent::Enable(const JSONObject& params) {
  UNREFERENCED_PARAMETER(params);
  bool initialized = connector_->RunScriptFile(kScriptFile);
  if (initialized) {
    return JSONObject(new base::DictionaryValue());
  } else {
    return connector_->ErrorResponse("Cannot create DOM inspector.");
  }
}

JSONObject DOMComponent::Disable(const JSONObject& params) {
  UNREFERENCED_PARAMETER(params);
  return JSONObject(new base::DictionaryValue());
}

JSONObject DOMComponent::GetDocument(const JSONObject& params) {
  return connector_->RunScriptCommand("dom.getDocument", params);
}

JSONObject DOMComponent::RequestChildNodes(const JSONObject& params) {
  return connector_->RunScriptCommand("dom.requestChildNodes", params);
}

JSONObject DOMComponent::RequestNode(const JSONObject& params) {
  return connector_->RunScriptCommand("dom.requestNode", params);
}

JSONObject DOMComponent::ResolveNode(const JSONObject& params) {
  return connector_->RunScriptCommand("dom.resolveNode", params);
}

// Unlike most other DOM command handlers, this one is not fully implemented
// in JavaScript. Instead, the JS object is used to look up the node from the
// parameters and return its bounding client rect, then the highlight itself
// is rendered by calling the C++ function |RenderHighlight| to set the render
// overlay.
JSONObject DOMComponent::HighlightNode(const JSONObject& params) {
  // Get the bounding rectangle of the specified node.
  JSONObject json_dom_rect =
      connector_->RunScriptCommand("dom.getBoundingClientRect", params);
  double x = 0.0;
  double y = 0.0;
  double width = 0.0;
  double height = 0.0;
  json_dom_rect->GetDouble("result.x", &x);
  json_dom_rect->GetDouble("result.y", &y);
  json_dom_rect->GetDouble("result.width", &width);
  json_dom_rect->GetDouble("result.height", &height);

  scoped_refptr<dom::DOMRect> dom_rect(
      new dom::DOMRect(static_cast<float>(x), static_cast<float>(y),
                       static_cast<float>(width), static_cast<float>(height)));

  // |highlight_config_value| still owned by |params|.
  base::DictionaryValue* highlight_config_value = NULL;
  bool got_highlight_config =
      params->GetDictionary(kHighlightConfig, &highlight_config_value);
  DCHECK(got_highlight_config);
  DCHECK(highlight_config_value);

  RenderHighlight(dom_rect, highlight_config_value);

  // Empty response.
  return JSONObject(new base::DictionaryValue());
}

JSONObject DOMComponent::HideHighlight(const JSONObject& params) {
  UNREFERENCED_PARAMETER(params);
  render_layer_->SetFrontLayer(scoped_refptr<render_tree::Node>());

  // Empty response.
  return JSONObject(new base::DictionaryValue());
}

void DOMComponent::RenderHighlight(
    const scoped_refptr<dom::DOMRect>& bounding_rect,
    const base::DictionaryValue* highlight_config_value) {
  // TODO: Should also render borders, etc.

  // Content color is optional in the parameters, so use a fallback.
  int r = 112;
  int g = 168;
  int b = 219;
  double a = 0.66;
  const base::DictionaryValue* content_color = NULL;
  bool got_content_color =
      highlight_config_value->GetDictionary(kContentColor, &content_color);
  if (got_content_color && content_color) {
    content_color->GetInteger(kR, &r);
    content_color->GetInteger(kG, &g);
    content_color->GetInteger(kB, &b);
    content_color->GetDouble(kA, &a);
  }
  render_tree::ColorRGBA color(r / 255.0f, g / 255.0f, b / 255.0f,
                               static_cast<float>(a));

  scoped_ptr<render_tree::Brush> background_brush(
      new render_tree::SolidColorBrush(color));
  scoped_refptr<render_tree::Node> rect = new render_tree::RectNode(
      math::RectF(bounding_rect->x(), bounding_rect->y(),
                  bounding_rect->width(), bounding_rect->height()),
      background_brush.Pass());
  render_layer_->SetFrontLayer(rect);
}

}  // namespace debug
}  // namespace cobalt
