// Copyright 2013 The Flutter 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 "flutter/display_list/display_list_attributes_testing.h"
#include "flutter/display_list/display_list_builder.h"
#include "flutter/display_list/display_list_comparable.h"
#include "flutter/display_list/display_list_mask_filter.h"
#include "flutter/display_list/types.h"
#include "gtest/gtest.h"

namespace flutter {
namespace testing {

TEST(DisplayListMaskFilter, BuilderSetGet) {
  DlBlurMaskFilter filter(SkBlurStyle::kNormal_SkBlurStyle, 5.0);
  DisplayListBuilder builder;
  ASSERT_EQ(builder.getMaskFilter(), nullptr);
  builder.setMaskFilter(&filter);
  ASSERT_NE(builder.getMaskFilter(), nullptr);
  ASSERT_TRUE(
      Equals(builder.getMaskFilter(), static_cast<DlMaskFilter*>(&filter)));
  builder.setMaskFilter(nullptr);
  ASSERT_EQ(builder.getMaskFilter(), nullptr);
}

TEST(DisplayListMaskFilter, FromSkiaNullFilter) {
  std::shared_ptr<DlMaskFilter> filter = DlMaskFilter::From(nullptr);
  ASSERT_EQ(filter, nullptr);
  ASSERT_EQ(filter.get(), nullptr);
}

TEST(DisplayListMaskFilter, FromSkiaBlurFilter) {
  sk_sp<SkMaskFilter> sk_filter =
      SkMaskFilter::MakeBlur(SkBlurStyle::kNormal_SkBlurStyle, 5.0);
  std::shared_ptr<DlMaskFilter> filter = DlMaskFilter::From(sk_filter);
  ASSERT_EQ(filter->type(), DlMaskFilterType::kUnknown);
  // We cannot recapture the blur parameters from an SkBlurMaskFilter
  ASSERT_EQ(filter->asBlur(), nullptr);
  ASSERT_EQ(filter->skia_object(), sk_filter);
}

TEST(DisplayListMaskFilter, BlurConstructor) {
  DlBlurMaskFilter filter(SkBlurStyle::kNormal_SkBlurStyle, 5.0);
}

TEST(DisplayListMaskFilter, BlurShared) {
  DlBlurMaskFilter filter(SkBlurStyle::kNormal_SkBlurStyle, 5.0);
  ASSERT_NE(filter.shared().get(), &filter);
  ASSERT_EQ(*filter.shared(), filter);
}

TEST(DisplayListMaskFilter, BlurAsBlur) {
  DlBlurMaskFilter filter(SkBlurStyle::kNormal_SkBlurStyle, 5.0);
  ASSERT_NE(filter.asBlur(), nullptr);
  ASSERT_EQ(filter.asBlur(), &filter);
}

TEST(DisplayListMaskFilter, BlurContents) {
  DlBlurMaskFilter filter(SkBlurStyle::kNormal_SkBlurStyle, 5.0);
  ASSERT_EQ(filter.style(), SkBlurStyle::kNormal_SkBlurStyle);
  ASSERT_EQ(filter.sigma(), 5.0);
}

TEST(DisplayListMaskFilter, BlurEquals) {
  DlBlurMaskFilter filter1(SkBlurStyle::kNormal_SkBlurStyle, 5.0);
  DlBlurMaskFilter filter2(SkBlurStyle::kNormal_SkBlurStyle, 5.0);
  TestEquals(filter1, filter2);
}

TEST(DisplayListMaskFilter, BlurNotEquals) {
  DlBlurMaskFilter filter1(SkBlurStyle::kNormal_SkBlurStyle, 5.0);
  DlBlurMaskFilter filter2(SkBlurStyle::kInner_SkBlurStyle, 5.0);
  DlBlurMaskFilter filter3(SkBlurStyle::kNormal_SkBlurStyle, 6.0);
  TestNotEquals(filter1, filter2, "Blur style differs");
  TestNotEquals(filter1, filter3, "blur radius differs");
}

TEST(DisplayListMaskFilter, UnknownConstructor) {
  DlUnknownMaskFilter filter(
      SkMaskFilter::MakeBlur(SkBlurStyle::kNormal_SkBlurStyle, 5.0));
}

TEST(DisplayListMaskFilter, UnknownShared) {
  DlUnknownMaskFilter filter(
      SkMaskFilter::MakeBlur(SkBlurStyle::kNormal_SkBlurStyle, 5.0));
  ASSERT_NE(filter.shared().get(), &filter);
  ASSERT_EQ(*filter.shared(), filter);
}

TEST(DisplayListMaskFilter, UnknownContents) {
  sk_sp<SkMaskFilter> sk_filter =
      SkMaskFilter::MakeBlur(SkBlurStyle::kNormal_SkBlurStyle, 5.0);
  DlUnknownMaskFilter filter(sk_filter);
  ASSERT_EQ(filter.skia_object(), sk_filter);
  ASSERT_EQ(filter.skia_object().get(), sk_filter.get());
}

TEST(DisplayListMaskFilter, UnknownEquals) {
  sk_sp<SkMaskFilter> sk_filter =
      SkMaskFilter::MakeBlur(SkBlurStyle::kNormal_SkBlurStyle, 5.0);
  DlUnknownMaskFilter filter1(sk_filter);
  DlUnknownMaskFilter filter2(sk_filter);
  TestEquals(filter1, filter2);
}

TEST(DisplayListMaskFilter, UnknownNotEquals) {
  // Even though the filter is the same, it is a different instance
  // and we cannot currently tell them apart because the Skia
  // MaskFilter objects do not implement ==
  DlUnknownMaskFilter filter1(
      SkMaskFilter::MakeBlur(SkBlurStyle::kNormal_SkBlurStyle, 5.0));
  DlUnknownMaskFilter filter2(
      SkMaskFilter::MakeBlur(SkBlurStyle::kNormal_SkBlurStyle, 5.0));
  TestNotEquals(filter1, filter2, "SkMaskFilter instance differs");
}

void testEquals(DlMaskFilter* a, DlMaskFilter* b) {
  // a and b have the same nullness or values
  ASSERT_TRUE(Equals(a, b));
  ASSERT_FALSE(NotEquals(a, b));
  ASSERT_TRUE(Equals(b, a));
  ASSERT_FALSE(NotEquals(b, a));
}

void testNotEquals(DlMaskFilter* a, DlMaskFilter* b) {
  // a and b do not have the same nullness or values
  ASSERT_FALSE(Equals(a, b));
  ASSERT_TRUE(NotEquals(a, b));
  ASSERT_FALSE(Equals(b, a));
  ASSERT_TRUE(NotEquals(b, a));
}

void testEquals(std::shared_ptr<const DlMaskFilter> a, DlMaskFilter* b) {
  // a and b have the same nullness or values
  ASSERT_TRUE(Equals(a, b));
  ASSERT_FALSE(NotEquals(a, b));
  ASSERT_TRUE(Equals(b, a));
  ASSERT_FALSE(NotEquals(b, a));
}

void testNotEquals(std::shared_ptr<const DlMaskFilter> a, DlMaskFilter* b) {
  // a and b do not have the same nullness or values
  ASSERT_FALSE(Equals(a, b));
  ASSERT_TRUE(NotEquals(a, b));
  ASSERT_FALSE(Equals(b, a));
  ASSERT_TRUE(NotEquals(b, a));
}

void testEquals(std::shared_ptr<const DlMaskFilter> a,
                std::shared_ptr<const DlMaskFilter> b) {
  // a and b have the same nullness or values
  ASSERT_TRUE(Equals(a, b));
  ASSERT_FALSE(NotEquals(a, b));
  ASSERT_TRUE(Equals(b, a));
  ASSERT_FALSE(NotEquals(b, a));
}

void testNotEquals(std::shared_ptr<const DlMaskFilter> a,
                   std::shared_ptr<const DlMaskFilter> b) {
  // a and b do not have the same nullness or values
  ASSERT_FALSE(Equals(a, b));
  ASSERT_TRUE(NotEquals(a, b));
  ASSERT_FALSE(Equals(b, a));
  ASSERT_TRUE(NotEquals(b, a));
}

TEST(DisplayListMaskFilter, ComparableTemplates) {
  DlBlurMaskFilter filter1a(SkBlurStyle::kNormal_SkBlurStyle, 3.0);
  DlBlurMaskFilter filter1b(SkBlurStyle::kNormal_SkBlurStyle, 3.0);
  DlBlurMaskFilter filter2(SkBlurStyle::kNormal_SkBlurStyle, 5.0);
  std::shared_ptr<DlMaskFilter> shared_null;

  // null to null
  testEquals(nullptr, nullptr);
  testEquals(shared_null, nullptr);
  testEquals(shared_null, shared_null);

  // ptr to null
  testNotEquals(&filter1a, nullptr);
  testNotEquals(&filter1b, nullptr);
  testNotEquals(&filter2, nullptr);

  // shared_ptr to null and shared_null to ptr
  testNotEquals(filter1a.shared(), nullptr);
  testNotEquals(filter1b.shared(), nullptr);
  testNotEquals(filter2.shared(), nullptr);
  testNotEquals(shared_null, &filter1a);
  testNotEquals(shared_null, &filter1b);
  testNotEquals(shared_null, &filter2);

  // ptr to ptr
  testEquals(&filter1a, &filter1a);
  testEquals(&filter1a, &filter1b);
  testEquals(&filter1b, &filter1b);
  testEquals(&filter2, &filter2);
  testNotEquals(&filter1a, &filter2);

  // shared_ptr to ptr
  testEquals(filter1a.shared(), &filter1a);
  testEquals(filter1a.shared(), &filter1b);
  testEquals(filter1b.shared(), &filter1b);
  testEquals(filter2.shared(), &filter2);
  testNotEquals(filter1a.shared(), &filter2);
  testNotEquals(filter1b.shared(), &filter2);
  testNotEquals(filter2.shared(), &filter1a);
  testNotEquals(filter2.shared(), &filter1b);

  // shared_ptr to shared_ptr
  testEquals(filter1a.shared(), filter1a.shared());
  testEquals(filter1a.shared(), filter1b.shared());
  testEquals(filter1b.shared(), filter1b.shared());
  testEquals(filter2.shared(), filter2.shared());
  testNotEquals(filter1a.shared(), filter2.shared());
  testNotEquals(filter1b.shared(), filter2.shared());
  testNotEquals(filter2.shared(), filter1a.shared());
  testNotEquals(filter2.shared(), filter1b.shared());
}

}  // namespace testing
}  // namespace flutter
