// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.h"

#include "third_party/blink/renderer/platform/geometry/geometry_as_json.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/graphics/logging_canvas.h"
#include "third_party/blink/renderer/platform/json/json_values.h"
#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
#include "third_party/blink/renderer/platform/wtf/text/text_stream.h"

namespace blink {

namespace {

typedef HashMap<int, int> RenderingContextMap;

static String PointerAsString(const void* ptr) {
  WTF::TextStream ts;
  ts << ptr;
  return ts.Release();
}

void AddFlattenInheritedTransformJSON(const GraphicsLayer* layer,
                                      JSONObject& json) {
  if (layer->Parent() && !layer->Parent()->ShouldFlattenTransform())
    json.SetBoolean("flattenInheritedTransform", false);
}

void AddTransformJSONProperties(const GraphicsLayer* layer,
                                JSONObject& json,
                                RenderingContextMap& rendering_context_map) {
  const TransformationMatrix& transform = layer->Transform();
  if (!transform.IsIdentity())
    json.SetArray("transform", TransformAsJSONArray(transform));

  if (!transform.IsIdentityOrTranslation())
    json.SetArray("origin", PointAsJSONArray(layer->TransformOrigin()));

  AddFlattenInheritedTransformJSON(layer, json);

  if (int rendering_context3d = layer->GetRenderingContext3D()) {
    auto it = rendering_context_map.find(rendering_context3d);
    int context_id = rendering_context_map.size() + 1;
    if (it == rendering_context_map.end())
      rendering_context_map.Set(rendering_context3d, context_id);
    else
      context_id = it->value;

    json.SetInteger("renderingContext", context_id);
  }
}

std::unique_ptr<JSONObject> GraphicsLayerAsJSON(
    const GraphicsLayer* layer,
    LayerTreeFlags flags,
    RenderingContextMap& rendering_context_map,
    const FloatPoint& position) {
  std::unique_ptr<JSONObject> json = JSONObject::Create();

  if (flags & kLayerTreeIncludesDebugInfo)
    json->SetString("this", PointerAsString(layer));

  json->SetString("name", layer->DebugName());

  if (position != FloatPoint())
    json->SetArray("position", PointAsJSONArray(position));

  if (flags & kLayerTreeIncludesDebugInfo &&
      layer->OffsetFromLayoutObject() != IntSize()) {
    json->SetArray("offsetFromLayoutObject",
                   SizeAsJSONArray(layer->OffsetFromLayoutObject()));
  }

  if (layer->Size() != IntSize())
    json->SetArray("bounds", SizeAsJSONArray(layer->Size()));

  if (layer->Opacity() != 1)
    json->SetDouble("opacity", layer->Opacity());

  if (layer->GetBlendMode() != BlendMode::kNormal) {
    json->SetString("blendMode", CompositeOperatorName(kCompositeSourceOver,
                                                       layer->GetBlendMode()));
  }

  if (layer->IsRootForIsolatedGroup())
    json->SetBoolean("isolate", true);

  if (layer->ContentsOpaque())
    json->SetBoolean("contentsOpaque", true);

  if (!layer->DrawsContent())
    json->SetBoolean("drawsContent", false);

  if (!layer->ContentsAreVisible())
    json->SetBoolean("contentsVisible", false);

  if (!layer->BackfaceVisibility())
    json->SetString("backfaceVisibility", "hidden");

  if (flags & kLayerTreeIncludesDebugInfo)
    json->SetString("client", PointerAsString(&layer->Client()));

  if (layer->BackgroundColor().Alpha()) {
    json->SetString("backgroundColor",
                    layer->BackgroundColor().NameForLayoutTreeAsText());
  }

  if (flags & kOutputAsLayerTree) {
    AddTransformJSONProperties(layer, *json, rendering_context_map);
    if (!layer->ShouldFlattenTransform())
      json->SetBoolean("shouldFlattenTransform", false);
    ScrollableArea* scrollable_area = layer->GetScrollableArea();
    if (scrollable_area && scrollable_area->ScrollPosition() != FloatPoint()) {
      json->SetArray("scrollPosition",
                     PointAsJSONArray(scrollable_area->ScrollPosition()));
    }
  }

  if ((flags & kLayerTreeIncludesPaintInvalidations) &&
      layer->Client().IsTrackingRasterInvalidations() &&
      layer->GetRasterInvalidationTracking()) {
    layer->GetRasterInvalidationTracking()->AsJSON(json.get());
  }

  GraphicsLayerPaintingPhase painting_phase = layer->PaintingPhase();
  if ((flags & kLayerTreeIncludesPaintingPhases) && painting_phase) {
    std::unique_ptr<JSONArray> painting_phases_json = JSONArray::Create();
    if (painting_phase & kGraphicsLayerPaintBackground)
      painting_phases_json->PushString("GraphicsLayerPaintBackground");
    if (painting_phase & kGraphicsLayerPaintForeground)
      painting_phases_json->PushString("GraphicsLayerPaintForeground");
    if (painting_phase & kGraphicsLayerPaintMask)
      painting_phases_json->PushString("GraphicsLayerPaintMask");
    if (painting_phase & kGraphicsLayerPaintChildClippingMask)
      painting_phases_json->PushString("GraphicsLayerPaintChildClippingMask");
    if (painting_phase & kGraphicsLayerPaintAncestorClippingMask) {
      painting_phases_json->PushString(
          "GraphicsLayerPaintAncestorClippingMask");
    }
    if (painting_phase & kGraphicsLayerPaintOverflowContents)
      painting_phases_json->PushString("GraphicsLayerPaintOverflowContents");
    if (painting_phase & kGraphicsLayerPaintCompositedScroll)
      painting_phases_json->PushString("GraphicsLayerPaintCompositedScroll");
    if (painting_phase & kGraphicsLayerPaintDecoration)
      painting_phases_json->PushString("GraphicsLayerPaintDecoration");
    json->SetArray("paintingPhases", std::move(painting_phases_json));
  }

  if (flags & kLayerTreeIncludesClipAndScrollParents) {
    if (layer->HasScrollParent())
      json->SetBoolean("hasScrollParent", true);
    if (layer->HasClipParent())
      json->SetBoolean("hasClipParent", true);
  }

  if (flags &
      (kLayerTreeIncludesDebugInfo | kLayerTreeIncludesCompositingReasons)) {
    bool debug = flags & kLayerTreeIncludesDebugInfo;
    {
      std::unique_ptr<JSONArray> compositing_reasons_json = JSONArray::Create();
      CompositingReasons compositing_reasons = layer->GetCompositingReasons();
      auto names = debug ? CompositingReason::Descriptions(compositing_reasons)
                         : CompositingReason::ShortNames(compositing_reasons);
      for (const char* name : names)
        compositing_reasons_json->PushString(name);
      json->SetArray("compositingReasons", std::move(compositing_reasons_json));
    }
    {
      std::unique_ptr<JSONArray> squashing_disallowed_reasons_json =
          JSONArray::Create();
      SquashingDisallowedReasons squashing_disallowed_reasons =
          layer->GetSquashingDisallowedReasons();
      auto names = debug ? SquashingDisallowedReason::Descriptions(
                               squashing_disallowed_reasons)
                         : SquashingDisallowedReason::ShortNames(
                               squashing_disallowed_reasons);
      for (const char* name : names)
        squashing_disallowed_reasons_json->PushString(name);
      json->SetArray("squashingDisallowedReasons",
                     std::move(squashing_disallowed_reasons_json));
    }
  }

  if (layer->MaskLayer()) {
    std::unique_ptr<JSONArray> mask_layer_json = JSONArray::Create();
    mask_layer_json->PushObject(
        GraphicsLayerAsJSON(layer->MaskLayer(), flags, rendering_context_map,
                            layer->MaskLayer()->GetPosition()));
    json->SetArray("maskLayer", std::move(mask_layer_json));
  }

  if (layer->ContentsClippingMaskLayer()) {
    std::unique_ptr<JSONArray> contents_clipping_mask_layer_json =
        JSONArray::Create();
    contents_clipping_mask_layer_json->PushObject(GraphicsLayerAsJSON(
        layer->ContentsClippingMaskLayer(), flags, rendering_context_map,
        layer->ContentsClippingMaskLayer()->GetPosition()));
    json->SetArray("contentsClippingMaskLayer",
                   std::move(contents_clipping_mask_layer_json));
  }

  if (layer->HasLayerState() && (flags & (kLayerTreeIncludesDebugInfo |
                                          kLayerTreeIncludesPaintRecords))) {
    json->SetString("layerState", layer->GetPropertyTreeState().ToString());
    json->SetValue("layerOffset",
                   PointAsJSONArray(layer->GetOffsetFromTransformNode()));
  }

#if DCHECK_IS_ON()
  if (layer->DrawsContent() && (flags & kLayerTreeIncludesPaintRecords))
    json->SetValue("paintRecord", RecordAsJSON(*layer->CapturePaintRecord()));
#endif

  return json;
}

class LayersAsJSONArray {
 public:
  LayersAsJSONArray(LayerTreeFlags flags)
      : flags_(flags),
        next_transform_id_(1),
        layers_json_(JSONArray::Create()),
        transforms_json_(JSONArray::Create()) {}

  // Outputs the layer tree rooted at |layer| as a JSON array, in paint order,
  // and the transform tree also as a JSON array.
  std::unique_ptr<JSONObject> operator()(const GraphicsLayer& layer) {
    auto json = JSONObject::Create();
    Walk(layer, 0, FloatPoint());
    json->SetArray("layers", std::move(layers_json_));
    if (transforms_json_->size())
      json->SetArray("transforms", std::move(transforms_json_));
    return json;
  }

  JSONObject* AddTransformJSON(int& transform_id) {
    auto transform_json = JSONObject::Create();
    int parent_transform_id = transform_id;
    transform_id = next_transform_id_++;
    transform_json->SetInteger("id", transform_id);
    if (parent_transform_id)
      transform_json->SetInteger("parent", parent_transform_id);
    auto* result = transform_json.get();
    transforms_json_->PushObject(std::move(transform_json));
    return result;
  }

  static FloatPoint ScrollPosition(const GraphicsLayer& layer) {
    if (const auto* scrollable_area = layer.GetScrollableArea())
      return scrollable_area->ScrollPosition();
    return FloatPoint();
  }

  void AddLayer(const GraphicsLayer& layer,
                int& transform_id,
                FloatPoint& position) {
    FloatPoint scroll_position = ScrollPosition(layer);
    if (scroll_position != FloatPoint()) {
      // Output scroll position as a transform.
      auto* scroll_translate_json = AddTransformJSON(transform_id);
      scroll_translate_json->SetArray(
          "transform", TransformAsJSONArray(TransformationMatrix().Translate(
                           -scroll_position.X(), -scroll_position.Y())));
      AddFlattenInheritedTransformJSON(&layer, *scroll_translate_json);
    }

    if (!layer.Transform().IsIdentity() || layer.GetRenderingContext3D() ||
        layer.GetCompositingReasons() & CompositingReason::k3DTransform) {
      if (position != FloatPoint()) {
        // Output position offset as a transform.
        auto* position_translate_json = AddTransformJSON(transform_id);
        position_translate_json->SetArray(
            "transform", TransformAsJSONArray(TransformationMatrix().Translate(
                             position.X(), position.Y())));
        AddFlattenInheritedTransformJSON(&layer, *position_translate_json);
        if (layer.Parent() && !layer.Parent()->ShouldFlattenTransform()) {
          position_translate_json->SetBoolean("flattenInheritedTransform",
                                              false);
        }
        position = FloatPoint();
      }

      if (!layer.Transform().IsIdentity() || layer.GetRenderingContext3D()) {
        auto* transform_json = AddTransformJSON(transform_id);
        AddTransformJSONProperties(&layer, *transform_json,
                                   rendering_context_map_);
      }
    }

    auto json =
        GraphicsLayerAsJSON(&layer, flags_, rendering_context_map_, position);
    if (transform_id)
      json->SetInteger("transform", transform_id);
    layers_json_->PushObject(std::move(json));
  }

  void Walk(const GraphicsLayer& layer,
            int parent_transform_id,
            const FloatPoint& parent_position) {
    FloatPoint position = parent_position + layer.GetPosition();
    int transform_id = parent_transform_id;
    AddLayer(layer, transform_id, position);
    for (auto* const child : layer.Children())
      Walk(*child, transform_id, position);
  }

 private:
  LayerTreeFlags flags_;
  int next_transform_id_;
  RenderingContextMap rendering_context_map_;
  std::unique_ptr<JSONArray> layers_json_;
  std::unique_ptr<JSONArray> transforms_json_;
};

// This is the SPv1 version of ContentLayerClientImpl::LayerAsJSON().
std::unique_ptr<JSONObject> GraphicsLayerTreeAsJSON(
    const GraphicsLayer* layer,
    LayerTreeFlags flags,
    RenderingContextMap& rendering_context_map) {
  std::unique_ptr<JSONObject> json = GraphicsLayerAsJSON(
      layer, flags, rendering_context_map, layer->GetPosition());

  if (layer->Children().size()) {
    std::unique_ptr<JSONArray> children_json = JSONArray::Create();
    for (size_t i = 0; i < layer->Children().size(); i++) {
      children_json->PushObject(GraphicsLayerTreeAsJSON(
          layer->Children()[i], flags, rendering_context_map));
    }
    json->SetArray("children", std::move(children_json));
  }

  return json;
}

}  // namespace

std::unique_ptr<JSONObject> GraphicsLayerTreeAsJSON(const GraphicsLayer* layer,
                                                    LayerTreeFlags flags) {
  if (flags & kOutputAsLayerTree) {
    RenderingContextMap rendering_context_map;
    return GraphicsLayerTreeAsJSON(layer, flags, rendering_context_map);
  }

  return LayersAsJSONArray(flags)(*layer);
}

String GraphicsLayerTreeAsTextForTesting(const GraphicsLayer* layer,
                                         LayerTreeFlags flags) {
  return GraphicsLayerTreeAsJSON(layer, flags)->ToPrettyJSONString();
}

}  // namespace blink

#if DCHECK_IS_ON()
void showGraphicsLayerTree(const blink::GraphicsLayer* layer) {
  if (!layer) {
    LOG(ERROR) << "Cannot showGraphicsLayerTree for (nil).";
    return;
  }

  String output = blink::GraphicsLayerTreeAsTextForTesting(layer, 0xffffffff);
  LOG(ERROR) << output.Utf8().data();
}

void showGraphicsLayers(const blink::GraphicsLayer* layer) {
  if (!layer) {
    LOG(ERROR) << "Cannot showGraphicsLayers for (nil).";
    return;
  }

  String output = blink::GraphicsLayerTreeAsTextForTesting(
      layer, 0xffffffff & ~blink::kOutputAsLayerTree);
  LOG(ERROR) << output.Utf8().data();
}
#endif
