// Copyright 2016 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/platform/testing/picture_matchers.h"

#include <utility>

#include "third_party/blink/renderer/platform/geometry/float_quad.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPicture.h"

namespace blink {

namespace {

class DrawsRectangleCanvas : public SkCanvas {
 public:
  DrawsRectangleCanvas()
      : SkCanvas(800, 600),
        save_count_(0),
        alpha_(255),
        alpha_save_layer_count_(-1) {}
  const Vector<RectWithColor>& RectsWithColor() const { return rects_; }

  void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
    SkPoint quad[4];
    getTotalMatrix().mapRectToQuad(quad, rect);

    SkRect device_rect;
    device_rect.set(quad, 4);
    SkIRect device_clip_bounds;
    FloatRect clipped_rect;
    if (getDeviceClipBounds(&device_clip_bounds) &&
        device_rect.intersect(SkRect::Make(device_clip_bounds)))
      clipped_rect = device_rect;

    unsigned paint_alpha = static_cast<unsigned>(paint.getAlpha());
    SkPaint paint_with_alpha(paint);
    paint_with_alpha.setAlpha(static_cast<U8CPU>(alpha_ * paint_alpha / 255));
    Color color = Color(paint_with_alpha.getColor());

    rects_.emplace_back(clipped_rect, color);
    SkCanvas::onDrawRect(rect, paint);
  }

  SkCanvas::SaveLayerStrategy getSaveLayerStrategy(
      const SaveLayerRec& rec) override {
    save_count_++;
    unsigned layer_alpha = static_cast<unsigned>(rec.fPaint->getAlpha());
    if (layer_alpha < 255) {
      DCHECK_EQ(alpha_save_layer_count_, -1);
      alpha_save_layer_count_ = save_count_;
      alpha_ = layer_alpha;
    }
    return SkCanvas::getSaveLayerStrategy(rec);
  }

  void willSave() override {
    save_count_++;
    SkCanvas::willSave();
  }

  void willRestore() override {
    DCHECK_GT(save_count_, 0);
    if (alpha_save_layer_count_ == save_count_) {
      alpha_ = 255;
      alpha_save_layer_count_ = -1;
    }
    save_count_--;
    SkCanvas::willRestore();
  }

 private:
  Vector<RectWithColor> rects_;
  int save_count_;
  unsigned alpha_;
  int alpha_save_layer_count_;
};

class DrawsRectanglesMatcher
    : public testing::MatcherInterface<const SkPicture&> {
 public:
  DrawsRectanglesMatcher(const Vector<RectWithColor>& rects_with_color)
      : rects_with_color_(rects_with_color) {}

  bool MatchAndExplain(const SkPicture& picture,
                       testing::MatchResultListener* listener) const override {
    DrawsRectangleCanvas canvas;
    picture.playback(&canvas);
    const auto& actual_rects = canvas.RectsWithColor();
    if (actual_rects.size() != rects_with_color_.size()) {
      *listener << "which draws " << actual_rects.size() << " rects";
      return false;
    }

    for (unsigned index = 0; index < actual_rects.size(); index++) {
      const auto& actual_rect_with_color = actual_rects[index];
      const auto& expect_rect_with_color = rects_with_color_[index];

      if (EnclosingIntRect(actual_rect_with_color.rect) !=
              EnclosingIntRect(expect_rect_with_color.rect) ||
          actual_rect_with_color.color != expect_rect_with_color.color) {
        if (listener->IsInterested()) {
          *listener << "at index " << index << " which draws "
                    << actual_rect_with_color.rect << " with color "
                    << actual_rect_with_color.color.Serialized().Ascii().data()
                    << "\n";
        }
        return false;
      }
    }

    return true;
  }

  void DescribeTo(::std::ostream* os) const override {
    *os << "\n";
    for (unsigned index = 0; index < rects_with_color_.size(); index++) {
      const auto& rect_with_color = rects_with_color_[index];
      *os << "at index " << index << " rect draws " << rect_with_color.rect
          << " with color " << rect_with_color.color.Serialized().Ascii().data()
          << "\n";
    }
  }

 private:
  const Vector<RectWithColor> rects_with_color_;
};

}  // namespace

testing::Matcher<const SkPicture&> DrawsRectangle(const FloatRect& rect,
                                                  Color color) {
  Vector<RectWithColor> rects_with_color;
  rects_with_color.push_back(RectWithColor(rect, color));
  return testing::MakeMatcher(new DrawsRectanglesMatcher(rects_with_color));
}

testing::Matcher<const SkPicture&> DrawsRectangles(
    const Vector<RectWithColor>& rects_with_color) {
  return testing::MakeMatcher(new DrawsRectanglesMatcher(rects_with_color));
}

}  // namespace blink
