// Copyright 2019 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/backend/overlay_agent.h"

#include "cobalt/math/clamp.h"
#include "cobalt/math/rect_f.h"
#include "cobalt/render_tree/brush.h"
#include "cobalt/render_tree/color_rgba.h"
#include "cobalt/render_tree/composition_node.h"
#include "cobalt/render_tree/rect_node.h"

namespace cobalt {
namespace debug {
namespace backend {

using base::Value;
using math::Clamp;
using render_tree::ColorRGBA;

namespace {
// Definitions from the set specified here:
// https://chromedevtools.github.io/devtools-protocol/tot/Overlay
constexpr char kInspectorDomain[] = "Overlay";

// File to load JavaScript Overlay DevTools domain implementation from.
constexpr char kScriptFile[] = "overlay_agent.js";

// Returns the float value of a param, or 0.0 if undefined or non-numeric.
float GetFloatParam(const Value* params, base::StringPiece key) {
  if (!params || !params->is_dict()) return 0.0f;
  const Value* v = params->FindKey(key);
  if (!v || !(v->is_double() || v->is_int())) return 0.0f;
  return static_cast<float>(v->GetDouble());
}

// Returns an RGBA color defined by a param, or transparent if undefined.
ColorRGBA RenderColor(const Value* params) {
  float r = GetFloatParam(params, "r") / 255.0f;
  float g = GetFloatParam(params, "g") / 255.0f;
  float b = GetFloatParam(params, "b") / 255.0f;
  float a = GetFloatParam(params, "a");
  return ColorRGBA(Clamp(r, 0.0f, 1.0f), Clamp(g, 0.0f, 1.0f),
                   Clamp(b, 0.0f, 1.0f), Clamp(a, 0.0f, 1.0f));
}

// Returns a rectangle to render according to the params for the DevTools
// "Overlay.highlightRect" command.
// https://chromedevtools.github.io/devtools-protocol/tot/Overlay#method-highlightRect
scoped_refptr<render_tree::RectNode> RenderHighlightRect(const Value* params) {
  float x = GetFloatParam(params, "x");
  float y = GetFloatParam(params, "y");
  float width = GetFloatParam(params, "width");
  float height = GetFloatParam(params, "height");
  ColorRGBA color(RenderColor(params->FindKey("color")));
  const Value* outline_param = params->FindKey("outlineColor");
  ColorRGBA outline_color(RenderColor(outline_param));
  float outline_width = outline_param ? 1.0f : 0.0f;
  return base::MakeRefCounted<render_tree::RectNode>(
      math::RectF(x, y, width, height),
      std::make_unique<render_tree::SolidColorBrush>(color),
      std::make_unique<render_tree::Border>(render_tree::BorderSide(
          outline_width, render_tree::kBorderStyleSolid, outline_color)));
}

}  // namespace

OverlayAgent::OverlayAgent(DebugDispatcher* dispatcher,
                           std::unique_ptr<RenderLayer> render_layer)
    : dispatcher_(dispatcher),
      render_layer_(std::move(render_layer)),
      ALLOW_THIS_IN_INITIALIZER_LIST(commands_(this, kInspectorDomain)) {
  DCHECK(dispatcher_);
  DCHECK(render_layer_);

  commands_["disable"] = &OverlayAgent::Disable;
  commands_["enable"] = &OverlayAgent::Enable;
  commands_["highlightNode"] = &OverlayAgent::HighlightNode;
  commands_["highlightRect"] = &OverlayAgent::HighlightRect;
  commands_["hideHighlight"] = &OverlayAgent::HideHighlight;
}

void OverlayAgent::Thaw(JSONObject agent_state) {
  dispatcher_->AddDomain(kInspectorDomain, commands_.Bind());
  script_loaded_ = dispatcher_->RunScriptFile(kScriptFile);
  DLOG_IF(ERROR, !script_loaded_) << "Failed to load " << kScriptFile;
}

JSONObject OverlayAgent::Freeze() {
  dispatcher_->RemoveDomain(kInspectorDomain);
  return JSONObject();
}

void OverlayAgent::Enable(Command command) {
  if (script_loaded_) {
    enabled_ = true;
    command.SendResponse();
  } else {
    command.SendErrorResponse(Command::kInternalError,
                              "Cannot create Overlay inspector.");
  }
}

void OverlayAgent::Disable(Command command) {
  enabled_ = false;
  command.SendResponse();
}

void OverlayAgent::HighlightNode(Command command) {
  if (!enabled_) {
    command.SendErrorResponse(Command::kInvalidRequest,
                              "Overlay inspector not enabled.");
    return;
  }
  // Use the injected JavaScript helper to get the rectangles to highlight for
  // the specified node.
  JSONObject rects_response = dispatcher_->RunScriptCommand(
      "Overlay._highlightNodeRects", command.GetParams());
  const Value* highlight_rects =
      rects_response->FindPath({"result", "highlightRects"});
  if (!highlight_rects) {
    command.SendErrorResponse(Command::kInvalidParams,
                              "Can't get node highlights.");
    return;
  }

  // Render all the highlight rects as children of a CompositionNode.
  render_tree::CompositionNode::Builder builder;
  for (const Value& rect_params : highlight_rects->GetList()) {
    builder.AddChild(RenderHighlightRect(&rect_params));
  }
  render_layer_->SetFrontLayer(
      base::MakeRefCounted<render_tree::CompositionNode>(builder));

  command.SendResponse();
}

void OverlayAgent::HighlightRect(Command command) {
  JSONObject params = JSONParse(command.GetParams());
  render_layer_->SetFrontLayer(RenderHighlightRect(params.get()));
  command.SendResponse();
}

void OverlayAgent::HideHighlight(Command command) {
  render_layer_->SetFrontLayer(scoped_refptr<render_tree::Node>());
  command.SendResponse();
}

}  // namespace backend
}  // namespace debug
}  // namespace cobalt
