/*
 * Copyright (C) 2012 Apple Inc. All rights reserved.
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.h"

#include <memory>

#include "base/stl_util.h"
#include "cc/base/region.h"
#include "cc/layers/picture_layer.h"
#include "third_party/blink/public/platform/web_float_point.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
#include "third_party/blink/renderer/core/inspector/inspected_frames.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/graphics/compositing_reasons.h"
#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/graphics/picture_snapshot.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "ui/gfx/geometry/rect.h"

namespace blink {

using protocol::Array;
using protocol::Maybe;
using protocol::Response;
unsigned InspectorLayerTreeAgent::last_snapshot_id_;

inline String IdForLayer(const cc::Layer* layer) {
  return String::Number(layer->id());
}

static std::unique_ptr<protocol::DOM::Rect> BuildObjectForRect(
    const gfx::Rect& rect) {
  return protocol::DOM::Rect::create()
      .setX(rect.x())
      .setY(rect.y())
      .setHeight(rect.height())
      .setWidth(rect.width())
      .build();
}

static std::unique_ptr<protocol::LayerTree::ScrollRect> BuildScrollRect(
    const gfx::Rect& rect,
    const String& type) {
  std::unique_ptr<protocol::DOM::Rect> rect_object = BuildObjectForRect(rect);
  std::unique_ptr<protocol::LayerTree::ScrollRect> scroll_rect_object =
      protocol::LayerTree::ScrollRect::create()
          .setRect(std::move(rect_object))
          .setType(type)
          .build();
  return scroll_rect_object;
}

static std::unique_ptr<Array<protocol::LayerTree::ScrollRect>>
BuildScrollRectsForLayer(const cc::Layer* layer, bool report_wheel_scrollers) {
  std::unique_ptr<Array<protocol::LayerTree::ScrollRect>> scroll_rects =
      Array<protocol::LayerTree::ScrollRect>::create();
  const cc::Region& non_fast_scrollable_rects =
      layer->non_fast_scrollable_region();
  for (const gfx::Rect& rect : non_fast_scrollable_rects) {
    scroll_rects->addItem(BuildScrollRect(
        IntRect(rect),
        protocol::LayerTree::ScrollRect::TypeEnum::RepaintsOnScroll));
  }
  const cc::Region& touch_event_handler_region =
      layer->touch_action_region().region();

  for (const gfx::Rect& rect : touch_event_handler_region) {
    scroll_rects->addItem(BuildScrollRect(
        IntRect(rect),
        protocol::LayerTree::ScrollRect::TypeEnum::TouchEventHandler));
  }
  if (report_wheel_scrollers) {
    scroll_rects->addItem(BuildScrollRect(
        // TODO(yutak): This truncates the floating point position to integers.
        gfx::Rect(layer->position().x(), layer->position().y(),
                  layer->bounds().width(), layer->bounds().height()),
        protocol::LayerTree::ScrollRect::TypeEnum::WheelEventHandler));
  }
  return scroll_rects->length() ? std::move(scroll_rects) : nullptr;
}

// TODO(flackr): We should be getting the sticky position constraints from the
// property tree once blink is able to access them. https://crbug.com/754339
static const cc::Layer* FindLayerByElementId(const cc::Layer* root,
                                             CompositorElementId element_id) {
  if (root->element_id() == element_id)
    return root;
  for (auto child : root->children()) {
    if (const auto* layer = FindLayerByElementId(child.get(), element_id))
      return layer;
  }
  return nullptr;
}

static std::unique_ptr<protocol::LayerTree::StickyPositionConstraint>
BuildStickyInfoForLayer(const cc::Layer* root, const cc::Layer* layer) {
  cc::LayerStickyPositionConstraint constraints =
      layer->sticky_position_constraint();
  if (!constraints.is_sticky)
    return nullptr;

  std::unique_ptr<protocol::DOM::Rect> sticky_box_rect =
      BuildObjectForRect(constraints.scroll_container_relative_sticky_box_rect);

  std::unique_ptr<protocol::DOM::Rect> containing_block_rect =
      BuildObjectForRect(
          constraints.scroll_container_relative_containing_block_rect);

  std::unique_ptr<protocol::LayerTree::StickyPositionConstraint>
      constraints_obj =
          protocol::LayerTree::StickyPositionConstraint::create()
              .setStickyBoxRect(std::move(sticky_box_rect))
              .setContainingBlockRect(std::move(containing_block_rect))
              .build();
  if (constraints.nearest_element_shifting_sticky_box) {
    constraints_obj->setNearestLayerShiftingStickyBox(String::Number(
        FindLayerByElementId(root,
                             constraints.nearest_element_shifting_sticky_box)
            ->id()));
  }
  if (constraints.nearest_element_shifting_containing_block) {
    constraints_obj->setNearestLayerShiftingContainingBlock(String::Number(
        FindLayerByElementId(
            root, constraints.nearest_element_shifting_containing_block)
            ->id()));
  }

  return constraints_obj;
}

static std::unique_ptr<protocol::LayerTree::Layer> BuildObjectForLayer(
    const cc::Layer* root,
    const cc::Layer* layer,
    bool report_wheel_event_listeners) {
  bool using_layer_list =
      RuntimeEnabledFeatures::CompositeAfterPaintEnabled() ||
      RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled();

  // When the front-end doesn't show internal layers, it will use the the first
  // DrawsContent layer as the root of the shown layer tree. This doesn't work
  // for layer list because the non-DrawsContent root layer is the parent of
  // all DrawsContent layers. We have to cheat the front-end by setting
  // drawsContent to true for the root layer.
  bool draws_content =
      (using_layer_list && root == layer) || layer->DrawsContent();

  std::unique_ptr<protocol::LayerTree::Layer> layer_object =
      protocol::LayerTree::Layer::create()
          .setLayerId(IdForLayer(layer))
          .setOffsetX(using_layer_list ? 0 : layer->position().x())
          .setOffsetY(using_layer_list ? 0 : layer->position().y())
          .setWidth(layer->bounds().width())
          .setHeight(layer->bounds().height())
          .setPaintCount(layer->paint_count())
          .setDrawsContent(draws_content)
          .build();

  if (auto node_id = layer->owner_node_id())
    layer_object->setBackendNodeId(node_id);

  if (const auto* parent = layer->parent())
    layer_object->setParentLayerId(IdForLayer(parent));

  gfx::Transform transform;
  gfx::Point3F transform_origin;
  if (using_layer_list) {
    transform = layer->ScreenSpaceTransform();
  } else {
    transform = layer->transform();
    transform_origin = layer->transform_origin();
  }

  if (!transform.IsIdentity()) {
    auto transform_array = Array<double>::create();
    for (int col = 0; col < 4; ++col) {
      for (int row = 0; row < 4; ++row)
        transform_array->addItem(transform.matrix().get(row, col));
    }
    layer_object->setTransform(std::move(transform_array));
    // FIXME: rename these to setTransformOrigin*
    if (layer->bounds().width() > 0) {
      layer_object->setAnchorX(transform_origin.x() / layer->bounds().width());
    } else {
      layer_object->setAnchorX(0.f);
    }
    if (layer->bounds().height() > 0) {
      layer_object->setAnchorY(transform_origin.y() / layer->bounds().height());
    } else {
      layer_object->setAnchorY(0.f);
    }
    layer_object->setAnchorZ(transform_origin.z());
  }
  std::unique_ptr<Array<protocol::LayerTree::ScrollRect>> scroll_rects =
      BuildScrollRectsForLayer(layer, report_wheel_event_listeners);
  if (scroll_rects)
    layer_object->setScrollRects(std::move(scroll_rects));
  std::unique_ptr<protocol::LayerTree::StickyPositionConstraint> sticky_info =
      BuildStickyInfoForLayer(root, layer);
  if (sticky_info)
    layer_object->setStickyPositionConstraint(std::move(sticky_info));
  return layer_object;
}

InspectorLayerTreeAgent::InspectorLayerTreeAgent(
    InspectedFrames* inspected_frames,
    Client* client)
    : inspected_frames_(inspected_frames),
      client_(client),
      suppress_layer_paint_events_(false) {}

InspectorLayerTreeAgent::~InspectorLayerTreeAgent() = default;

void InspectorLayerTreeAgent::Trace(blink::Visitor* visitor) {
  visitor->Trace(inspected_frames_);
  InspectorBaseAgent::Trace(visitor);
}

void InspectorLayerTreeAgent::Restore() {
  // We do not re-enable layer agent automatically after navigation. This is
  // because it depends on DOMAgent and node ids in particular, so we let
  // front-end request document and re-enable the agent manually after this.
}

Response InspectorLayerTreeAgent::enable() {
  instrumenting_agents_->addInspectorLayerTreeAgent(this);
  Document* document = inspected_frames_->Root()->GetDocument();
  if (!document)
    return Response::Error("The root frame doesn't have document");

  if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() ||
      RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
    if (document->Lifecycle().GetState() >= DocumentLifecycle::kPaintClean)
      LayerTreePainted();
  } else if (document->Lifecycle().GetState() >=
             DocumentLifecycle::kCompositingClean) {
    LayerTreeDidChange();
  }
  return Response::OK();
}

Response InspectorLayerTreeAgent::disable() {
  instrumenting_agents_->removeInspectorLayerTreeAgent(this);
  snapshot_by_id_.clear();
  return Response::OK();
}

void InspectorLayerTreeAgent::LayerTreeDidChange() {
  DCHECK(!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() &&
         !RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
  GetFrontend()->layerTreeDidChange(BuildLayerTree());
}

void InspectorLayerTreeAgent::DidPaint(const cc::Layer* layer,
                                       const LayoutRect& rect) {
  DCHECK(!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() &&
         !RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
  if (suppress_layer_paint_events_)
    return;

  // Should only happen for LocalFrameView paints when compositing is off.
  // Consider different instrumentation method for that.
  if (!layer)
    return;

  std::unique_ptr<protocol::DOM::Rect> dom_rect = protocol::DOM::Rect::create()
                                                      .setX(rect.X())
                                                      .setY(rect.Y())
                                                      .setWidth(rect.Width())
                                                      .setHeight(rect.Height())
                                                      .build();
  GetFrontend()->layerPainted(IdForLayer(layer), std::move(dom_rect));
}

void InspectorLayerTreeAgent::LayerTreePainted() {
  DCHECK(RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() ||
         RuntimeEnabledFeatures::CompositeAfterPaintEnabled());

  GetFrontend()->layerTreeDidChange(BuildLayerTree());

  for (const auto& layer :
       inspected_frames_->Root()->View()->RootCcLayer()->children()) {
    if (!layer->update_rect().IsEmpty()) {
      GetFrontend()->layerPainted(IdForLayer(layer.get()),
                                  BuildObjectForRect(layer->update_rect()));
    }
  }
}

std::unique_ptr<Array<protocol::LayerTree::Layer>>
InspectorLayerTreeAgent::BuildLayerTree() {
  const auto* root_layer = RootLayer();
  if (!root_layer)
    return nullptr;

  std::unique_ptr<Array<protocol::LayerTree::Layer>> layers =
      Array<protocol::LayerTree::Layer>::create();
  auto* root_frame = inspected_frames_->Root();
  auto* layer_for_scrolling =
      root_frame->View()->LayoutViewport()->LayerForScrolling();
  int scrolling_layer_id =
      layer_for_scrolling ? layer_for_scrolling->CcLayer()->id() : 0;
  bool have_blocking_wheel_event_handlers =
      root_frame->GetChromeClient().EventListenerProperties(
          root_frame, cc::EventListenerClass::kMouseWheel) ==
      cc::EventListenerProperties::kBlocking;

  GatherLayers(root_layer, layers, have_blocking_wheel_event_handlers,
               scrolling_layer_id);
  return layers;
}

void InspectorLayerTreeAgent::GatherLayers(
    const cc::Layer* layer,
    std::unique_ptr<Array<protocol::LayerTree::Layer>>& layers,
    bool has_wheel_event_handlers,
    int scrolling_layer_id) {
  if (client_->IsInspectorLayer(layer))
    return;
  int layer_id = layer->id();
  layers->addItem(BuildObjectForLayer(
      RootLayer(), layer,
      has_wheel_event_handlers && layer_id == scrolling_layer_id));
  for (auto child : layer->children()) {
    GatherLayers(child.get(), layers, has_wheel_event_handlers,
                 scrolling_layer_id);
  }
}

const cc::Layer* InspectorLayerTreeAgent::RootLayer() {
  return inspected_frames_->Root()->View()->RootCcLayer();
}

static const cc::Layer* FindLayerById(const cc::Layer* root, int layer_id) {
  if (root->id() == layer_id)
    return root;
  for (auto child : root->children()) {
    if (const auto* layer = FindLayerById(child.get(), layer_id))
      return layer;
  }
  return nullptr;
}

Response InspectorLayerTreeAgent::LayerById(const String& layer_id,
                                            const cc::Layer*& result) {
  bool ok;
  int id = layer_id.ToInt(&ok);
  if (!ok)
    return Response::Error("Invalid layer id");

  result = FindLayerById(RootLayer(), id);
  if (!result)
    return Response::Error("No layer matching given id found");
  return Response::OK();
}

Response InspectorLayerTreeAgent::compositingReasons(
    const String& layer_id,
    std::unique_ptr<Array<String>>* reason_strings) {
  const cc::Layer* layer = nullptr;
  Response response = LayerById(layer_id, layer);
  if (!response.isSuccess())
    return response;
  CompositingReasons reasons = layer->compositing_reasons();
  *reason_strings = Array<String>::create();
  for (const char* name : CompositingReason::ShortNames(reasons))
    (*reason_strings)->addItem(name);
  return Response::OK();
}

Response InspectorLayerTreeAgent::makeSnapshot(const String& layer_id,
                                               String* snapshot_id) {
  const cc::Layer* layer = nullptr;
  Response response = LayerById(layer_id, layer);
  if (!response.isSuccess())
    return response;
  if (!layer->DrawsContent())
    return Response::Error("Layer does not draw content");

  suppress_layer_paint_events_ = true;

  // If we hit a devtool break point in the middle of document lifecycle, for
  // example, https://crbug.com/788219, this will prevent crash when clicking
  // the "layer" panel.
  if (inspected_frames_->Root()->GetDocument() && inspected_frames_->Root()
                                                      ->GetDocument()
                                                      ->Lifecycle()
                                                      .LifecyclePostponed())
    return Response::Error("Layer does not draw content");

  inspected_frames_->Root()->View()->UpdateAllLifecyclePhases(
      DocumentLifecycle::LifecycleUpdateReason::kOther);

  suppress_layer_paint_events_ = false;

  auto picture = layer->GetPicture();
  if (!picture)
    return Response::Error("Layer does not produce picture");

  auto snapshot = base::MakeRefCounted<PictureSnapshot>(std::move(picture));
  *snapshot_id = String::Number(++last_snapshot_id_);
  bool new_entry = snapshot_by_id_.insert(*snapshot_id, snapshot).is_new_entry;
  DCHECK(new_entry);
  return Response::OK();
}

Response InspectorLayerTreeAgent::loadSnapshot(
    std::unique_ptr<Array<protocol::LayerTree::PictureTile>> tiles,
    String* snapshot_id) {
  if (!tiles->length())
    return Response::Error("Invalid argument, no tiles provided");
  if (tiles->length() > UINT_MAX)
    return Response::Error("Invalid argument, too many tiles provided");
  wtf_size_t tiles_length = static_cast<wtf_size_t>(tiles->length());
  Vector<scoped_refptr<PictureSnapshot::TilePictureStream>> decoded_tiles;
  decoded_tiles.Grow(tiles_length);
  for (wtf_size_t i = 0; i < tiles_length; ++i) {
    protocol::LayerTree::PictureTile* tile = tiles->get(i);
    decoded_tiles[i] = base::AdoptRef(new PictureSnapshot::TilePictureStream());
    decoded_tiles[i]->layer_offset.Set(tile->getX(), tile->getY());
    const protocol::Binary& data = tile->getPicture();
    decoded_tiles[i]->picture =
        SkPicture::MakeFromData(data.data(), data.size());
  }
  scoped_refptr<PictureSnapshot> snapshot =
      PictureSnapshot::Load(decoded_tiles);
  if (!snapshot)
    return Response::Error("Invalid snapshot format");
  if (snapshot->IsEmpty())
    return Response::Error("Empty snapshot");

  *snapshot_id = String::Number(++last_snapshot_id_);
  bool new_entry = snapshot_by_id_.insert(*snapshot_id, snapshot).is_new_entry;
  DCHECK(new_entry);
  return Response::OK();
}

Response InspectorLayerTreeAgent::releaseSnapshot(const String& snapshot_id) {
  SnapshotById::iterator it = snapshot_by_id_.find(snapshot_id);
  if (it == snapshot_by_id_.end())
    return Response::Error("Snapshot not found");
  snapshot_by_id_.erase(it);
  return Response::OK();
}

Response InspectorLayerTreeAgent::GetSnapshotById(
    const String& snapshot_id,
    const PictureSnapshot*& result) {
  SnapshotById::iterator it = snapshot_by_id_.find(snapshot_id);
  if (it == snapshot_by_id_.end())
    return Response::Error("Snapshot not found");
  result = it->value.get();
  return Response::OK();
}

Response InspectorLayerTreeAgent::replaySnapshot(const String& snapshot_id,
                                                 Maybe<int> from_step,
                                                 Maybe<int> to_step,
                                                 Maybe<double> scale,
                                                 String* data_url) {
  const PictureSnapshot* snapshot = nullptr;
  Response response = GetSnapshotById(snapshot_id, snapshot);
  if (!response.isSuccess())
    return response;
  Vector<char> base64_data = snapshot->Replay(
      from_step.fromMaybe(0), to_step.fromMaybe(0), scale.fromMaybe(1.0));
  if (base64_data.IsEmpty())
    return Response::Error("Image encoding failed");
  static constexpr char kUrlPrefix[] = "data:image/png;base64,";
  StringBuilder url;
  url.ReserveCapacity(sizeof(kUrlPrefix) + base64_data.size());
  url.Append(kUrlPrefix);
  url.Append(base64_data.begin(), base64_data.size());
  *data_url = url.ToString();
  return Response::OK();
}

static void ParseRect(protocol::DOM::Rect* object, FloatRect* rect) {
  *rect = FloatRect(object->getX(), object->getY(), object->getWidth(),
                    object->getHeight());
}

Response InspectorLayerTreeAgent::profileSnapshot(
    const String& snapshot_id,
    Maybe<int> min_repeat_count,
    Maybe<double> min_duration,
    Maybe<protocol::DOM::Rect> clip_rect,
    std::unique_ptr<protocol::Array<protocol::Array<double>>>* out_timings) {
  const PictureSnapshot* snapshot = nullptr;
  Response response = GetSnapshotById(snapshot_id, snapshot);
  if (!response.isSuccess())
    return response;
  FloatRect rect;
  if (clip_rect.isJust())
    ParseRect(clip_rect.fromJust(), &rect);
  auto timings =
      snapshot->Profile(min_repeat_count.fromMaybe(1),
                        TimeDelta::FromSecondsD(min_duration.fromMaybe(0)),
                        clip_rect.isJust() ? &rect : nullptr);
  *out_timings = Array<Array<double>>::create();
  for (const auto& row : timings) {
    std::unique_ptr<Array<double>> out_row = Array<double>::create();
    for (TimeDelta delta : row)
      out_row->addItem(delta.InSecondsF());
    (*out_timings)->addItem(std::move(out_row));
  }
  return Response::OK();
}

Response InspectorLayerTreeAgent::snapshotCommandLog(
    const String& snapshot_id,
    std::unique_ptr<Array<protocol::DictionaryValue>>* command_log) {
  const PictureSnapshot* snapshot = nullptr;
  Response response = GetSnapshotById(snapshot_id, snapshot);
  if (!response.isSuccess())
    return response;
  protocol::ErrorSupport errors;
  std::unique_ptr<protocol::Value> log_value = protocol::StringUtil::parseJSON(
      snapshot->SnapshotCommandLog()->ToJSONString());
  *command_log =
      Array<protocol::DictionaryValue>::fromValue(log_value.get(), &errors);
  if (errors.hasErrors())
    return Response::Error(errors.errors());
  return Response::OK();
}

}  // namespace blink
