// Copyright 2015 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 "services/gfx/compositor/graph/nodes.h"

#include <ostream>

#include "base/logging.h"
#include "mojo/services/gfx/composition/cpp/formatting.h"
#include "mojo/skia/type_converters.h"
#include "services/gfx/compositor/graph/scene_content.h"
#include "services/gfx/compositor/graph/snapshot.h"
#include "services/gfx/compositor/graph/transform_pair.h"
#include "services/gfx/compositor/render/render_image.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/utils/SkMatrix44.h"

namespace compositor {
namespace {
SkColor MakeSkColor(const mojo::gfx::composition::Color& color) {
  return SkColorSetARGBInline(color.alpha, color.red, color.green, color.blue);
}

void SetPaintForBlend(SkPaint* paint, mojo::gfx::composition::Blend* blend) {
  DCHECK(paint);
  if (blend)
    paint->setAlpha(blend->alpha);
}

bool Contains(const SkRect& bounds, const SkPoint& point) {
  return point.x() >= bounds.left() && point.x() < bounds.right() &&
         point.y() >= bounds.top() && point.y() < bounds.bottom();
}
}  // namespace

Node::Node(uint32_t node_id,
           std::unique_ptr<TransformPair> content_transform,
           mojo::RectFPtr content_clip,
           mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior,
           Combinator combinator,
           const std::vector<uint32_t>& child_node_ids)
    : node_id_(node_id),
      content_transform_(std::move(content_transform)),
      content_clip_(content_clip.Pass()),
      hit_test_behavior_(hit_test_behavior.Pass()),
      combinator_(combinator),
      child_node_ids_(child_node_ids) {}

Node::~Node() {}

std::string Node::FormattedLabel(const SceneContent* content) const {
  return content->FormattedLabelForNode(node_id_);
}

bool Node::RecordContent(SceneContentBuilder* builder) const {
  DCHECK(builder);

  for (const auto& child_node_id : child_node_ids_) {
    if (!builder->RequireNode(child_node_id, node_id_))
      return false;
  }
  return true;
}

Snapshot::Disposition Node::RecordSnapshot(const SceneContent* content,
                                           SnapshotBuilder* builder) const {
  DCHECK(content);
  DCHECK(builder);

  switch (combinator_) {
    // MERGE: All or nothing.
    case Combinator::MERGE: {
      for (uint32_t child_node_id : child_node_ids_) {
        const Node* child_node = content->GetNode(child_node_id);
        DCHECK(child_node);
        Snapshot::Disposition disposition =
            builder->SnapshotNode(child_node, content);
        if (disposition == Snapshot::Disposition::kCycle)
          return disposition;
        if (disposition == Snapshot::Disposition::kBlocked) {
          if (builder->block_log()) {
            *builder->block_log()
                << "Node with MERGE combinator blocked since "
                   "one of its children is blocked: "
                << FormattedLabel(content) << ", blocked child "
                << child_node->FormattedLabel(content) << std::endl;
          }
          return disposition;
        }
      }
      return Snapshot::Disposition::kSuccess;
    }

    // PRUNE: Silently discard blocked children.
    case Combinator::PRUNE: {
      for (uint32_t child_node_id : child_node_ids_) {
        const Node* child_node = content->GetNode(child_node_id);
        DCHECK(child_node);
        Snapshot::Disposition disposition =
            builder->SnapshotNode(child_node, content);
        if (disposition == Snapshot::Disposition::kCycle)
          return disposition;
      }
      return Snapshot::Disposition::kSuccess;
    }

    // FALLBACK: Keep only the first unblocked child.
    case Combinator::FALLBACK: {
      if (child_node_ids_.empty())
        return Snapshot::Disposition::kSuccess;
      for (uint32_t child_node_id : child_node_ids_) {
        const Node* child_node = content->GetNode(child_node_id);
        DCHECK(child_node);
        Snapshot::Disposition disposition =
            builder->SnapshotNode(child_node, content);
        if (disposition != Snapshot::Disposition::kBlocked)
          return disposition;
      }
      if (builder->block_log()) {
        *builder->block_log() << "Node with FALLBACK combinator blocked since "
                                 "all of its children are blocked: "
                              << FormattedLabel(content) << std::endl;
      }
      return Snapshot::Disposition::kBlocked;
    }

    default: {
      if (builder->block_log()) {
        *builder->block_log()
            << "Unrecognized combinator: " << FormattedLabel(content)
            << std::endl;
      }
      return Snapshot::Disposition::kBlocked;
    }
  }
}

template <typename Func>
void Node::TraverseSnapshottedChildren(const SceneContent* content,
                                       const Snapshot* snapshot,
                                       const Func& func) const {
  DCHECK(content);
  DCHECK(snapshot);

  switch (combinator_) {
    // MERGE: All or nothing.
    case Combinator::MERGE: {
      for (uint32_t child_node_id : child_node_ids_) {
        const Node* child_node = content->GetNode(child_node_id);
        DCHECK(child_node);
        DCHECK(!snapshot->IsNodeBlocked(child_node));
        if (!func(child_node))
          return;
      }
      return;
    }

    // PRUNE: Silently discard blocked children.
    case Combinator::PRUNE: {
      for (uint32_t child_node_id : child_node_ids_) {
        const Node* child_node = content->GetNode(child_node_id);
        DCHECK(child_node);
        if (!snapshot->IsNodeBlocked(child_node) && !func(child_node))
          return;
      }
      return;
    }

    // FALLBACK: Keep only the first unblocked child.
    case Combinator::FALLBACK: {
      if (child_node_ids_.empty())
        return;
      for (uint32_t child_node_id : child_node_ids_) {
        const Node* child_node = content->GetNode(child_node_id);
        DCHECK(child_node);
        if (!snapshot->IsNodeBlocked(child_node)) {
          func(child_node);  // don't care about the result because we
          return;            // always stop after the first one
        }
      }
      NOTREACHED();
      return;
    }

    default: {
      NOTREACHED();
      return;
    }
  }
}

void Node::RecordPicture(const SceneContent* content,
                         const Snapshot* snapshot,
                         SkCanvas* canvas) const {
  DCHECK(content);
  DCHECK(snapshot);
  DCHECK(canvas);

  const bool must_save = content_transform_ || content_clip_;
  if (must_save) {
    canvas->save();
    if (content_transform_)
      canvas->concat(content_transform_->forward());
    if (content_clip_)
      canvas->clipRect(content_clip_->To<SkRect>());
  }

  RecordPictureInner(content, snapshot, canvas);

  if (must_save)
    canvas->restore();
}

void Node::RecordPictureInner(const SceneContent* content,
                              const Snapshot* snapshot,
                              SkCanvas* canvas) const {
  DCHECK(content);
  DCHECK(snapshot);
  DCHECK(canvas);

  TraverseSnapshottedChildren(
      content, snapshot,
      [this, content, snapshot, canvas](const Node* child_node) -> bool {
        child_node->RecordPicture(content, snapshot, canvas);
        return true;
      });
}

bool Node::HitTest(const SceneContent* content,
                   const Snapshot* snapshot,
                   const SkPoint& parent_point,
                   const SkMatrix44& global_to_parent_transform,
                   mojo::Array<mojo::gfx::composition::HitPtr>* hits) const {
  DCHECK(content);
  DCHECK(snapshot);
  DCHECK(hits);

  // TODO(jeffbrown): These calculations should probably be happening using
  // a 4x4 matrix instead.
  SkPoint local_point(parent_point);
  SkMatrix global_to_local_transform(global_to_parent_transform);
  if (content_transform_) {
    // TODO(jeffbrown): Defer matrix multiplications using a matrix stack.
    local_point = content_transform_->InverseMapPoint(parent_point);
    global_to_local_transform.preConcat(content_transform_->GetInverse());
  }

  if (content_clip_ && !Contains(content_clip_->To<SkRect>(), local_point))
    return false;

  bool opaque_children = false;
  if (!hit_test_behavior_ || !hit_test_behavior_->prune) {
    opaque_children = HitTestInner(content, snapshot, local_point,
                                   global_to_local_transform, hits);
  }

  return HitTestSelf(content, snapshot, local_point, global_to_local_transform,
                     hits) ||
         opaque_children;
}

bool Node::HitTestInner(
    const SceneContent* content,
    const Snapshot* snapshot,
    const SkPoint& local_point,
    const SkMatrix44& global_to_local_transform,
    mojo::Array<mojo::gfx::composition::HitPtr>* hits) const {
  DCHECK(content);
  DCHECK(snapshot);
  DCHECK(hits);

  // TODO(jeffbrown): Implement a more efficient way to traverse children in
  // reverse order.
  std::vector<const Node*> children;
  TraverseSnapshottedChildren(
      content, snapshot, [this, &children](const Node* child_node) -> bool {
        children.push_back(child_node);
        return true;
      });

  for (auto it = children.crbegin(); it != children.crend(); ++it) {
    if ((*it)->HitTest(content, snapshot, local_point,
                       global_to_local_transform, hits))
      return true;  // opaque child covering siblings
  }
  return false;
}

bool Node::HitTestSelf(
    const SceneContent* content,
    const Snapshot* snapshot,
    const SkPoint& local_point,
    const SkMatrix44& global_to_local_transform,
    mojo::Array<mojo::gfx::composition::HitPtr>* hits) const {
  DCHECK(content);
  DCHECK(snapshot);
  DCHECK(hits);

  if (!hit_test_behavior_ ||
      hit_test_behavior_->visibility ==
          mojo::gfx::composition::HitTestBehavior::Visibility::INVISIBLE)
    return false;

  if (hit_test_behavior_->hit_rect &&
      !Contains(hit_test_behavior_->hit_rect->To<SkRect>(), local_point))
    return false;

  auto hit = mojo::gfx::composition::Hit::New();
  hit->set_node(mojo::gfx::composition::NodeHit::New());
  hit->get_node()->node_id = node_id_;
  hit->get_node()->transform =
      mojo::ConvertTo<mojo::TransformPtr>(global_to_local_transform);
  hits->push_back(hit.Pass());
  return hit_test_behavior_->visibility ==
         mojo::gfx::composition::HitTestBehavior::Visibility::OPAQUE;
}

RectNode::RectNode(uint32_t node_id,
                   std::unique_ptr<TransformPair> content_transform,
                   mojo::RectFPtr content_clip,
                   mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior,
                   Combinator combinator,
                   const std::vector<uint32_t>& child_node_ids,
                   const mojo::RectF& content_rect,
                   const mojo::gfx::composition::Color& color)
    : Node(node_id,
           std::move(content_transform),
           content_clip.Pass(),
           hit_test_behavior.Pass(),
           combinator,
           child_node_ids),
      content_rect_(content_rect),
      color_(color) {}

RectNode::~RectNode() {}

void RectNode::RecordPictureInner(const SceneContent* content,
                                  const Snapshot* snapshot,
                                  SkCanvas* canvas) const {
  DCHECK(content);
  DCHECK(snapshot);
  DCHECK(canvas);

  SkPaint paint;
  paint.setColor(MakeSkColor(color_));
  canvas->drawRect(content_rect_.To<SkRect>(), paint);

  Node::RecordPictureInner(content, snapshot, canvas);
}

ImageNode::ImageNode(
    uint32_t node_id,
    std::unique_ptr<TransformPair> content_transform,
    mojo::RectFPtr content_clip,
    mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior,
    Combinator combinator,
    const std::vector<uint32_t>& child_node_ids,
    const mojo::RectF& content_rect,
    mojo::RectFPtr image_rect,
    uint32 image_resource_id,
    mojo::gfx::composition::BlendPtr blend)
    : Node(node_id,
           std::move(content_transform),
           content_clip.Pass(),
           hit_test_behavior.Pass(),
           combinator,
           child_node_ids),
      content_rect_(content_rect),
      image_rect_(image_rect.Pass()),
      image_resource_id_(image_resource_id),
      blend_(blend.Pass()) {}

ImageNode::~ImageNode() {}

bool ImageNode::RecordContent(SceneContentBuilder* builder) const {
  DCHECK(builder);

  return Node::RecordContent(builder) &&
         builder->RequireResource(image_resource_id_, Resource::Type::kImage,
                                  node_id());
}

void ImageNode::RecordPictureInner(const SceneContent* content,
                                   const Snapshot* snapshot,
                                   SkCanvas* canvas) const {
  DCHECK(content);
  DCHECK(snapshot);
  DCHECK(canvas);

  auto image_resource = static_cast<const ImageResource*>(
      content->GetResource(image_resource_id_, Resource::Type::kImage));
  DCHECK(image_resource);

  SkPaint paint;
  SetPaintForBlend(&paint, blend_.get());

  canvas->drawImageRect(image_resource->image()->image().get(),
                        image_rect_
                            ? image_rect_->To<SkRect>()
                            : SkRect::MakeWH(image_resource->image()->width(),
                                             image_resource->image()->height()),
                        content_rect_.To<SkRect>(), &paint);

  Node::RecordPictureInner(content, snapshot, canvas);
}

SceneNode::SceneNode(
    uint32_t node_id,
    std::unique_ptr<TransformPair> content_transform,
    mojo::RectFPtr content_clip,
    mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior,
    Combinator combinator,
    const std::vector<uint32_t>& child_node_ids,
    uint32_t scene_resource_id,
    uint32_t scene_version)
    : Node(node_id,
           std::move(content_transform),
           content_clip.Pass(),
           hit_test_behavior.Pass(),
           combinator,
           child_node_ids),
      scene_resource_id_(scene_resource_id),
      scene_version_(scene_version) {}

SceneNode::~SceneNode() {}

bool SceneNode::RecordContent(SceneContentBuilder* builder) const {
  DCHECK(builder);

  return Node::RecordContent(builder) &&
         builder->RequireResource(scene_resource_id_, Resource::Type::kScene,
                                  node_id());
}

Snapshot::Disposition SceneNode::RecordSnapshot(
    const SceneContent* content,
    SnapshotBuilder* builder) const {
  DCHECK(content);
  DCHECK(builder);

  Snapshot::Disposition disposition =
      builder->SnapshotReferencedScene(this, content);
  if (disposition != Snapshot::Disposition::kSuccess)
    return disposition;
  return Node::RecordSnapshot(content, builder);
}

void SceneNode::RecordPictureInner(const SceneContent* content,
                                   const Snapshot* snapshot,
                                   SkCanvas* canvas) const {
  DCHECK(content);
  DCHECK(snapshot);
  DCHECK(canvas);

  const SceneContent* resolved_content =
      snapshot->GetResolvedSceneContent(this);
  DCHECK(resolved_content);
  resolved_content->RecordPicture(snapshot, canvas);

  Node::RecordPictureInner(content, snapshot, canvas);
}

bool SceneNode::HitTestInner(
    const SceneContent* content,
    const Snapshot* snapshot,
    const SkPoint& local_point,
    const SkMatrix44& global_to_local_transform,
    mojo::Array<mojo::gfx::composition::HitPtr>* hits) const {
  DCHECK(content);
  DCHECK(snapshot);
  DCHECK(hits);

  if (Node::HitTestInner(content, snapshot, local_point,
                         global_to_local_transform, hits))
    return true;  // opaque child covering referenced scene

  const SceneContent* resolved_content =
      snapshot->GetResolvedSceneContent(this);
  DCHECK(resolved_content);

  mojo::gfx::composition::SceneHitPtr scene_hit;
  bool opaque = resolved_content->HitTest(
      snapshot, local_point, global_to_local_transform, &scene_hit);
  if (scene_hit) {
    auto hit = mojo::gfx::composition::Hit::New();
    hit->set_scene(scene_hit.Pass());
    hits->push_back(hit.Pass());
  }
  return opaque;
}

LayerNode::LayerNode(
    uint32_t node_id,
    std::unique_ptr<TransformPair> content_transform,
    mojo::RectFPtr content_clip,
    mojo::gfx::composition::HitTestBehaviorPtr hit_test_behavior,
    Combinator combinator,
    const std::vector<uint32_t>& child_node_ids,
    const mojo::RectF& layer_rect,
    mojo::gfx::composition::BlendPtr blend)
    : Node(node_id,
           std::move(content_transform),
           content_clip.Pass(),
           hit_test_behavior.Pass(),
           combinator,
           child_node_ids),
      layer_rect_(layer_rect),
      blend_(blend.Pass()) {}

LayerNode::~LayerNode() {}

void LayerNode::RecordPictureInner(const SceneContent* content,
                                   const Snapshot* snapshot,
                                   SkCanvas* canvas) const {
  DCHECK(content);
  DCHECK(snapshot);
  DCHECK(canvas);

  SkPaint paint;
  SetPaintForBlend(&paint, blend_.get());

  canvas->saveLayer(layer_rect_.To<SkRect>(), &paint);
  Node::RecordPictureInner(content, snapshot, canvas);
  canvas->restore();
}

}  // namespace compositor
