// Copyright 2016 Google Inc. 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
