// 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/animation/effect_stack.h"

#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/animation/animation_clock.h"
#include "third_party/blink/renderer/core/animation/animation_test_helpers.h"
#include "third_party/blink/renderer/core/animation/document_timeline.h"
#include "third_party/blink/renderer/core/animation/element_animations.h"
#include "third_party/blink/renderer/core/animation/interpolable_length.h"
#include "third_party/blink/renderer/core/animation/invalidatable_interpolation.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect_model.h"
#include "third_party/blink/renderer/core/animation/pending_animations.h"
#include "third_party/blink/renderer/core/animation/string_keyframe.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/heap/heap.h"

namespace blink {

using animation_test_helpers::EnsureInterpolatedValueCached;

class AnimationEffectStackTest : public PageTestBase {
 protected:
  void SetUp() override {
    PageTestBase::SetUp(IntSize());
    GetDocument().GetAnimationClock().ResetTimeForTesting();
    timeline = GetDocument().Timeline();
    element = GetDocument().CreateElementForBinding("foo");
  }

  Animation* Play(KeyframeEffect* effect, double start_time) {
    Animation* animation = timeline->Play(effect);
    animation->setStartTime(CSSNumberish::FromDouble(start_time * 1000));
    animation->Update(kTimingUpdateOnDemand);
    return animation;
  }

  void UpdateTimeline(base::TimeDelta time) {
    GetDocument().GetAnimationClock().UpdateTime(
        GetDocument().Timeline().CalculateZeroTime() + time);
    timeline->ServiceAnimations(kTimingUpdateForAnimationFrame);
  }

  size_t SampledEffectCount() {
    return element->EnsureElementAnimations()
        .GetEffectStack()
        .sampled_effects_.size();
  }

  KeyframeEffectModelBase* MakeEffectModel(CSSPropertyID id,
                                           const String& value) {
    StringKeyframeVector keyframes(2);
    keyframes[0] = MakeGarbageCollected<StringKeyframe>();
    keyframes[0]->SetOffset(0.0);
    keyframes[0]->SetCSSPropertyValue(
        id, value, SecureContextMode::kInsecureContext, nullptr);
    keyframes[1] = MakeGarbageCollected<StringKeyframe>();
    keyframes[1]->SetOffset(1.0);
    keyframes[1]->SetCSSPropertyValue(
        id, value, SecureContextMode::kInsecureContext, nullptr);
    return MakeGarbageCollected<StringKeyframeEffectModel>(keyframes);
  }

  InertEffect* MakeInertEffect(KeyframeEffectModelBase* effect) {
    Timing timing;
    timing.fill_mode = Timing::FillMode::BOTH;
    return MakeGarbageCollected<InertEffect>(
        effect, timing, false, AnimationTimeDelta(), base::nullopt);
  }

  KeyframeEffect* MakeKeyframeEffect(KeyframeEffectModelBase* effect,
                                     double duration = 10) {
    Timing timing;
    timing.fill_mode = Timing::FillMode::BOTH;
    timing.iteration_duration = AnimationTimeDelta::FromSecondsD(duration);
    return MakeGarbageCollected<KeyframeEffect>(element.Get(), effect, timing);
  }

  double GetFontSizeValue(
      const ActiveInterpolationsMap& active_interpolations) {
    ActiveInterpolations* interpolations =
        active_interpolations.at(PropertyHandle(GetCSSPropertyFontSize()));
    EnsureInterpolatedValueCached(interpolations, GetDocument(), element);

    const auto* typed_value =
        To<InvalidatableInterpolation>(*interpolations->at(0))
            .GetCachedValueForTesting();
    // font-size is stored as an |InterpolableLength|; here we assume pixels.
    EXPECT_TRUE(typed_value->GetInterpolableValue().IsLength());
    const InterpolableLength& length =
        To<InterpolableLength>(typed_value->GetInterpolableValue());
    return length.CreateCSSValue(kValueRangeAll)->GetDoubleValue();
  }

  double GetZIndexValue(const ActiveInterpolationsMap& active_interpolations) {
    ActiveInterpolations* interpolations =
        active_interpolations.at(PropertyHandle(GetCSSPropertyZIndex()));
    EnsureInterpolatedValueCached(interpolations, GetDocument(), element);

    const auto* typed_value =
        To<InvalidatableInterpolation>(*interpolations->at(0))
            .GetCachedValueForTesting();
    // z-index is stored as a straight number value.
    EXPECT_TRUE(typed_value->GetInterpolableValue().IsNumber());
    return To<InterpolableNumber>(&typed_value->GetInterpolableValue())
        ->Value();
  }

  Persistent<DocumentTimeline> timeline;
  Persistent<Element> element;
};

TEST_F(AnimationEffectStackTest, ElementAnimationsSorted) {
  Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kFontSize, "1px")),
       10);
  Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kFontSize, "2px")),
       15);
  Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kFontSize, "3px")), 5);
  ActiveInterpolationsMap result = EffectStack::ActiveInterpolations(
      &element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
      KeyframeEffect::kDefaultPriority);
  EXPECT_EQ(1u, result.size());
  EXPECT_EQ(GetFontSizeValue(result), 3);
}

TEST_F(AnimationEffectStackTest, NewAnimations) {
  Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kFontSize, "1px")),
       15);
  Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kZIndex, "2")), 10);
  HeapVector<Member<const InertEffect>> new_animations;
  InertEffect* inert1 =
      MakeInertEffect(MakeEffectModel(CSSPropertyID::kFontSize, "3px"));
  InertEffect* inert2 =
      MakeInertEffect(MakeEffectModel(CSSPropertyID::kZIndex, "4"));
  new_animations.push_back(inert1);
  new_animations.push_back(inert2);
  ActiveInterpolationsMap result = EffectStack::ActiveInterpolations(
      &element->GetElementAnimations()->GetEffectStack(), &new_animations,
      nullptr, KeyframeEffect::kDefaultPriority);
  EXPECT_EQ(2u, result.size());
  EXPECT_EQ(GetFontSizeValue(result), 3);
  EXPECT_EQ(GetZIndexValue(result), 4);
}

TEST_F(AnimationEffectStackTest, CancelledAnimations) {
  HeapHashSet<Member<const Animation>> cancelled_animations;
  Animation* animation = Play(
      MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kFontSize, "1px")), 0);
  cancelled_animations.insert(animation);
  Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kZIndex, "2")), 0);
  ActiveInterpolationsMap result = EffectStack::ActiveInterpolations(
      &element->GetElementAnimations()->GetEffectStack(), nullptr,
      &cancelled_animations, KeyframeEffect::kDefaultPriority);
  EXPECT_EQ(1u, result.size());
  EXPECT_EQ(GetZIndexValue(result), 2);
}

TEST_F(AnimationEffectStackTest, ClearedEffectsRemoved) {
  Animation* animation = Play(
      MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kFontSize, "1px")), 10);
  ActiveInterpolationsMap result = EffectStack::ActiveInterpolations(
      &element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
      KeyframeEffect::kDefaultPriority);
  EXPECT_EQ(1u, result.size());
  EXPECT_EQ(GetFontSizeValue(result), 1);

  animation->setEffect(nullptr);
  result = EffectStack::ActiveInterpolations(
      &element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
      KeyframeEffect::kDefaultPriority);
  EXPECT_EQ(0u, result.size());
}

TEST_F(AnimationEffectStackTest, ForwardsFillDiscarding) {
  Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kFontSize, "1px")), 2);
  Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kFontSize, "2px")), 6);
  Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kFontSize, "3px")), 4);
  GetDocument().GetPendingAnimations().Update(nullptr);

  // Because we will be forcing a naive GC that assumes there are no Oilpan
  // objects on the stack (e.g. passes BlinkGC::kNoHeapPointersOnStack), we have
  // to keep the ActiveInterpolationsMap in a Persistent.
  Persistent<ActiveInterpolationsMap> interpolations;

  UpdateTimeline(base::TimeDelta::FromSeconds(11));
  ThreadState::Current()->CollectAllGarbageForTesting();
  interpolations = MakeGarbageCollected<ActiveInterpolationsMap>(
      EffectStack::ActiveInterpolations(
          &element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
          KeyframeEffect::kDefaultPriority));
  EXPECT_EQ(1u, interpolations->size());
  EXPECT_EQ(GetFontSizeValue(*interpolations), 3);
  EXPECT_EQ(3u, SampledEffectCount());

  UpdateTimeline(base::TimeDelta::FromSeconds(13));
  ThreadState::Current()->CollectAllGarbageForTesting();
  interpolations = MakeGarbageCollected<ActiveInterpolationsMap>(
      EffectStack::ActiveInterpolations(
          &element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
          KeyframeEffect::kDefaultPriority));
  EXPECT_EQ(1u, interpolations->size());
  EXPECT_EQ(GetFontSizeValue(*interpolations), 3);
  EXPECT_EQ(3u, SampledEffectCount());

  UpdateTimeline(base::TimeDelta::FromSeconds(15));
  ThreadState::Current()->CollectAllGarbageForTesting();
  interpolations = MakeGarbageCollected<ActiveInterpolationsMap>(
      EffectStack::ActiveInterpolations(
          &element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
          KeyframeEffect::kDefaultPriority));
  EXPECT_EQ(1u, interpolations->size());
  EXPECT_EQ(GetFontSizeValue(*interpolations), 3);
  EXPECT_EQ(2u, SampledEffectCount());

  UpdateTimeline(base::TimeDelta::FromSeconds(17));
  ThreadState::Current()->CollectAllGarbageForTesting();
  interpolations = MakeGarbageCollected<ActiveInterpolationsMap>(
      EffectStack::ActiveInterpolations(
          &element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
          KeyframeEffect::kDefaultPriority));
  EXPECT_EQ(1u, interpolations->size());
  EXPECT_EQ(GetFontSizeValue(*interpolations), 3);
  EXPECT_EQ(1u, SampledEffectCount());
}

TEST_F(AnimationEffectStackTest, AffectsPropertiesCSSBitsetDefaultPriority) {
  Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kColor, "red")), 10);
  Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kTop, "1px")), 10);
  Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyID::kLeft, "1px")), 10);

  ASSERT_TRUE(element->GetElementAnimations());
  const EffectStack& effect_stack =
      element->GetElementAnimations()->GetEffectStack();

  EXPECT_FALSE(effect_stack.AffectsProperties(
      CSSBitset({CSSPropertyID::kBackgroundColor}),
      KeyframeEffect::kDefaultPriority));
  EXPECT_FALSE(effect_stack.AffectsProperties(
      CSSBitset({CSSPropertyID::kBackgroundColor, CSSPropertyID::kFontSize}),
      KeyframeEffect::kDefaultPriority));
  EXPECT_FALSE(effect_stack.AffectsProperties(
      CSSBitset({CSSPropertyID::kColor}), KeyframeEffect::kTransitionPriority));

  EXPECT_TRUE(effect_stack.AffectsProperties(CSSBitset({CSSPropertyID::kColor}),
                                             KeyframeEffect::kDefaultPriority));
  EXPECT_TRUE(effect_stack.AffectsProperties(CSSBitset({CSSPropertyID::kTop}),
                                             KeyframeEffect::kDefaultPriority));
  EXPECT_TRUE(effect_stack.AffectsProperties(CSSBitset({CSSPropertyID::kLeft}),
                                             KeyframeEffect::kDefaultPriority));
  EXPECT_TRUE(effect_stack.AffectsProperties(
      CSSBitset({CSSPropertyID::kColor, CSSPropertyID::kRight}),
      KeyframeEffect::kDefaultPriority));
  EXPECT_TRUE(effect_stack.AffectsProperties(
      CSSBitset({CSSPropertyID::kColor, CSSPropertyID::kTop}),
      KeyframeEffect::kDefaultPriority));
  EXPECT_FALSE(effect_stack.AffectsProperties(
      CSSBitset({CSSPropertyID::kColor}), KeyframeEffect::kTransitionPriority));
}

TEST_F(AnimationEffectStackTest, AffectsPropertiesCSSBitsetTransitionPriority) {
  Element* body = GetDocument().body();
  body->SetInlineStyleProperty(CSSPropertyID::kTransition, "color 10s");
  body->SetInlineStyleProperty(CSSPropertyID::kColor, "red");
  UpdateAllLifecyclePhasesForTest();

  body->SetInlineStyleProperty(CSSPropertyID::kColor, "blue");
  UpdateAllLifecyclePhasesForTest();

  ASSERT_TRUE(body->GetElementAnimations());
  const EffectStack& effect_stack =
      body->GetElementAnimations()->GetEffectStack();

  EXPECT_FALSE(effect_stack.AffectsProperties(
      CSSBitset({CSSPropertyID::kColor}), KeyframeEffect::kDefaultPriority));
  EXPECT_TRUE(effect_stack.AffectsProperties(
      CSSBitset({CSSPropertyID::kColor}), KeyframeEffect::kTransitionPriority));
  EXPECT_FALSE(effect_stack.AffectsProperties(
      CSSBitset({CSSPropertyID::kBackgroundColor}),
      KeyframeEffect::kTransitionPriority));
}

}  // namespace blink
