// Copyright 2017 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 "cc/animation/worklet_animation.h"

#include <utility>
#include "base/memory/ptr_util.h"
#include "cc/animation/scroll_timeline.h"
#include "cc/test/animation_test_common.h"
#include "cc/test/animation_timelines_test_common.h"
#include "cc/trees/property_tree.h"
#include "testing/gmock/include/gmock/gmock.h"

using ::testing::Mock;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::_;

namespace cc {

namespace {

class MockKeyframeEffect : public KeyframeEffect {
 public:
  MockKeyframeEffect() : KeyframeEffect(0) {}
  MOCK_METHOD1(Tick, void(base::TimeTicks monotonic_time));
};

class WorkletAnimationTest : public AnimationTimelinesTest {
 public:
  WorkletAnimationTest() = default;
  ~WorkletAnimationTest() override = default;

  void AttachWorkletAnimation() {
    client_.RegisterElement(element_id_, ElementListType::ACTIVE);

    worklet_animation_ = WrapRefCounted(
        new WorkletAnimation(1, worklet_animation_id_, "test_name", 1, nullptr,
                             nullptr, true /* controlling instance*/));
    worklet_animation_->AttachElement(element_id_);
    host_->AddAnimationTimeline(timeline_);
    timeline_->AttachAnimation(worklet_animation_);
  }

  scoped_refptr<WorkletAnimation> worklet_animation_;
  WorkletAnimationId worklet_animation_id_{11, 12};
};

class MockScrollTimeline : public ScrollTimeline {
 public:
  MockScrollTimeline()
      : ScrollTimeline(ElementId(),
                       ScrollTimeline::ScrollDown,
                       base::nullopt,
                       base::nullopt,
                       0,
                       KeyframeModel::FillMode::NONE) {}
  MOCK_CONST_METHOD2(CurrentTime,
                     base::Optional<base::TimeTicks>(const ScrollTree&, bool));
};

TEST_F(WorkletAnimationTest, NonImplInstanceDoesNotTickKeyframe) {
  std::unique_ptr<MockKeyframeEffect> effect =
      std::make_unique<MockKeyframeEffect>();
  MockKeyframeEffect* mock_effect = effect.get();

  scoped_refptr<WorkletAnimation> worklet_animation =
      WrapRefCounted(new WorkletAnimation(
          1, worklet_animation_id_, "test_name", 1, nullptr, nullptr,
          false /* not impl instance*/, std::move(effect)));

  EXPECT_CALL(*mock_effect, Tick(_)).Times(0);

  MutatorOutputState::AnimationState state(worklet_animation_id_);
  state.local_times.push_back(base::TimeDelta::FromSecondsD(1));
  worklet_animation->SetOutputState(state);
  worklet_animation->Tick(base::TimeTicks());
}

TEST_F(WorkletAnimationTest, LocalTimeIsUsedWhenTicking) {
  AttachWorkletAnimation();

  const float start_opacity = .7f;
  const float end_opacity = .3f;
  const double duration = 1.;

  const float expected_opacity =
      start_opacity + (end_opacity - start_opacity) / 2;
  AddOpacityTransitionToAnimation(worklet_animation_.get(), duration,
                                  start_opacity, end_opacity, true);

  KeyframeModel* keyframe_model =
      worklet_animation_->GetKeyframeModel(TargetProperty::OPACITY);
  // Impl side animation don't need synchronized start time.
  keyframe_model->set_needs_synchronized_start_time(false);

  base::TimeDelta local_time = base::TimeDelta::FromSecondsD(duration / 2);
  MutatorOutputState::AnimationState state(worklet_animation_id_);
  state.local_times.push_back(local_time);
  worklet_animation_->SetOutputState(state);

  worklet_animation_->Tick(base::TimeTicks());

  TestLayer* layer =
      client_.FindTestLayer(element_id_, ElementListType::ACTIVE);
  EXPECT_TRUE(layer->is_property_mutated(TargetProperty::OPACITY));
  client_.ExpectOpacityPropertyMutated(element_id_, ElementListType::ACTIVE,
                                       expected_opacity);
}

TEST_F(WorkletAnimationTest, CurrentTimeCorrectlyUsesScrollTimeline) {
  auto scroll_timeline = std::make_unique<MockScrollTimeline>();
  EXPECT_CALL(*scroll_timeline, CurrentTime(_, _))
      .WillRepeatedly(Return(
          (base::TimeTicks() + base::TimeDelta::FromMilliseconds(1234))));
  scoped_refptr<WorkletAnimation> worklet_animation =
      WorkletAnimation::Create(worklet_animation_id_, "test_name", 1,
                               std::move(scroll_timeline), nullptr);

  ScrollTree scroll_tree;
  std::unique_ptr<MutatorInputState> state =
      std::make_unique<MutatorInputState>();
  worklet_animation->UpdateInputState(state.get(), base::TimeTicks::Now(),
                                      scroll_tree, true);
  std::unique_ptr<AnimationWorkletInput> input =
      state->TakeWorkletState(worklet_animation_id_.worklet_id);
  EXPECT_EQ(1234, input->added_and_updated_animations[0].current_time);
}

TEST_F(WorkletAnimationTest,
       CurrentTimeFromRegularTimelineIsOffsetByStartTime) {
  scoped_refptr<WorkletAnimation> worklet_animation = WorkletAnimation::Create(
      worklet_animation_id_, "test_name", 1, nullptr, nullptr);

  base::TimeTicks first_ticks =
      base::TimeTicks() + base::TimeDelta::FromMillisecondsD(111);
  base::TimeTicks second_ticks =
      base::TimeTicks() + base::TimeDelta::FromMillisecondsD(111 + 123.4);
  base::TimeTicks third_ticks =
      base::TimeTicks() + base::TimeDelta::FromMillisecondsD(111 + 246.8);

  ScrollTree scroll_tree;
  std::unique_ptr<MutatorInputState> state =
      std::make_unique<MutatorInputState>();
  worklet_animation->UpdateInputState(state.get(), first_ticks, scroll_tree,
                                      true);
  // First state request sets the start time and thus current time should be 0.
  std::unique_ptr<AnimationWorkletInput> input =
      state->TakeWorkletState(worklet_animation_id_.worklet_id);
  EXPECT_EQ(0, input->added_and_updated_animations[0].current_time);
  state.reset(new MutatorInputState);
  worklet_animation->UpdateInputState(state.get(), second_ticks, scroll_tree,
                                      true);
  input = state->TakeWorkletState(worklet_animation_id_.worklet_id);
  EXPECT_EQ(123.4, input->updated_animations[0].current_time);
  // Should always offset from start time.
  state.reset(new MutatorInputState());
  worklet_animation->UpdateInputState(state.get(), third_ticks, scroll_tree,
                                      true);
  input = state->TakeWorkletState(worklet_animation_id_.worklet_id);
  EXPECT_EQ(246.8, input->updated_animations[0].current_time);
}

// Verifies correctness of current time when playback rate is set on
// initializing the animation and while the animation is playing.
TEST_F(WorkletAnimationTest, DocumentTimelineSetPlaybackRate) {
  const double playback_rate_double = 2;
  const double playback_rate_half = 0.5;
  scoped_refptr<WorkletAnimation> worklet_animation =
      WorkletAnimation::Create(worklet_animation_id_, "test_name",
                               playback_rate_double, nullptr, nullptr);

  base::TimeTicks first_ticks =
      base::TimeTicks() + base::TimeDelta::FromMillisecondsD(111);
  base::TimeTicks second_ticks =
      base::TimeTicks() + base::TimeDelta::FromMillisecondsD(111 + 123.4);
  base::TimeTicks third_ticks =
      base::TimeTicks() +
      base::TimeDelta::FromMillisecondsD(111 + 123.4 + 200.0);

  ScrollTree scroll_tree;
  std::unique_ptr<MutatorInputState> state =
      std::make_unique<MutatorInputState>();
  // Start the animation.
  worklet_animation->UpdateInputState(state.get(), first_ticks, scroll_tree,
                                      true);
  state.reset(new MutatorInputState);

  // Play until second_ticks.
  worklet_animation->UpdateInputState(state.get(), second_ticks, scroll_tree,
                                      true);
  std::unique_ptr<AnimationWorkletInput> input =
      state->TakeWorkletState(worklet_animation_id_.worklet_id);

  // Verify that the current time is updated twice faster than the timeline
  // time.
  EXPECT_EQ(123.4 * playback_rate_double,
            input->updated_animations[0].current_time);

  // Update the playback rate.
  worklet_animation->SetPlaybackRateForTesting(playback_rate_half);
  state.reset(new MutatorInputState());

  // Play until third_ticks.
  worklet_animation->UpdateInputState(state.get(), third_ticks, scroll_tree,
                                      true);
  input = state->TakeWorkletState(worklet_animation_id_.worklet_id);

  // Verify that the current time is updated half as fast as the timeline time.
  EXPECT_EQ(123.4 * playback_rate_double + 200.0 * playback_rate_half,
            input->updated_animations[0].current_time);
}

// Verifies correctness of current time when playback rate is set on
// initializing the scroll-linked animation and while the animation is playing.
TEST_F(WorkletAnimationTest, ScrollTimelineSetPlaybackRate) {
  const double playback_rate_double = 2;
  const double playback_rate_half = 0.5;
  auto scroll_timeline = std::make_unique<MockScrollTimeline>();

  EXPECT_CALL(*scroll_timeline, CurrentTime(_, _))
      // First UpdateInputState call.
      .WillOnce(
          Return(base::TimeTicks() + base::TimeDelta::FromMilliseconds(50)))
      // First UpdateInputState call.
      .WillOnce(
          Return(base::TimeTicks() + base::TimeDelta::FromMilliseconds(50)))
      // Second UpdateInputState call.
      .WillRepeatedly(
          Return(base::TimeTicks() + base::TimeDelta::FromMilliseconds(100)));

  scoped_refptr<WorkletAnimation> worklet_animation = WorkletAnimation::Create(
      worklet_animation_id_, "test_name", playback_rate_double,
      std::move(scroll_timeline), nullptr);

  ScrollTree scroll_tree;
  std::unique_ptr<MutatorInputState> state =
      std::make_unique<MutatorInputState>();
  // Start the animation.
  worklet_animation->UpdateInputState(state.get(), base::TimeTicks(),
                                      scroll_tree, true);
  std::unique_ptr<AnimationWorkletInput> input =
      state->TakeWorkletState(worklet_animation_id_.worklet_id);

  // Verify that the current time is updated twice faster than the timeline
  // time.
  EXPECT_EQ(50 * playback_rate_double,
            input->added_and_updated_animations[0].current_time);

  // Update the playback rate.
  worklet_animation->SetPlaybackRateForTesting(playback_rate_half);
  state.reset(new MutatorInputState());

  // Continue playing the animation.
  worklet_animation->UpdateInputState(state.get(), base::TimeTicks(),
                                      scroll_tree, true);
  input = state->TakeWorkletState(worklet_animation_id_.worklet_id);

  // Verify that the current time is updated half as fast as the timeline time.
  EXPECT_EQ(50 * playback_rate_double + 50 * playback_rate_half,
            input->updated_animations[0].current_time);
}

// This test verifies that worklet animation state is properly updated.
TEST_F(WorkletAnimationTest, UpdateInputStateProducesCorrectState) {
  AttachWorkletAnimation();

  const float start_opacity = .7f;
  const float end_opacity = .3f;
  const double duration = 1.;

  int keyframe_model_id = AddOpacityTransitionToAnimation(
      worklet_animation_.get(), duration, start_opacity, end_opacity, true);

  ScrollTree scroll_tree;
  std::unique_ptr<MutatorInputState> state =
      std::make_unique<MutatorInputState>();

  KeyframeModel* keyframe_model =
      worklet_animation_->GetKeyframeModel(TargetProperty::OPACITY);
  ASSERT_TRUE(keyframe_model);

  base::TimeTicks time;
  worklet_animation_->UpdateInputState(state.get(), time, scroll_tree, true);
  std::unique_ptr<AnimationWorkletInput> input =
      state->TakeWorkletState(worklet_animation_id_.worklet_id);
  EXPECT_EQ(input->added_and_updated_animations.size(), 1u);
  EXPECT_EQ("test_name", input->added_and_updated_animations[0].name);
  EXPECT_EQ(input->updated_animations.size(), 0u);
  EXPECT_EQ(input->removed_animations.size(), 0u);

  // The state of WorkletAnimation is updated to RUNNING after calling
  // UpdateInputState above.
  state.reset(new MutatorInputState());
  time += base::TimeDelta::FromSecondsD(0.1);
  worklet_animation_->UpdateInputState(state.get(), time, scroll_tree, true);
  input = state->TakeWorkletState(worklet_animation_id_.worklet_id);
  EXPECT_EQ(input->added_and_updated_animations.size(), 0u);
  EXPECT_EQ(input->updated_animations.size(), 1u);
  EXPECT_EQ(input->removed_animations.size(), 0u);

  // Operating on individual KeyframeModel doesn't affect the state of
  // WorkletAnimation.
  keyframe_model->SetRunState(KeyframeModel::FINISHED, time);
  state.reset(new MutatorInputState());
  time += base::TimeDelta::FromSecondsD(0.1);
  worklet_animation_->UpdateInputState(state.get(), time, scroll_tree, true);
  input = state->TakeWorkletState(worklet_animation_id_.worklet_id);
  EXPECT_EQ(input->added_and_updated_animations.size(), 0u);
  EXPECT_EQ(input->updated_animations.size(), 1u);
  EXPECT_EQ(input->removed_animations.size(), 0u);

  // WorkletAnimation sets state to REMOVED when JavaScript fires cancel() which
  // leads to RemoveKeyframeModel.
  worklet_animation_->RemoveKeyframeModel(keyframe_model_id);
  worklet_animation_->UpdateState(true, nullptr);
  state.reset(new MutatorInputState());
  worklet_animation_->UpdateInputState(state.get(), time, scroll_tree, true);
  input = state->TakeWorkletState(worklet_animation_id_.worklet_id);
  EXPECT_EQ(input->added_and_updated_animations.size(), 0u);
  EXPECT_EQ(input->updated_animations.size(), 0u);
  EXPECT_EQ(input->removed_animations.size(), 1u);
  EXPECT_EQ(input->removed_animations[0], worklet_animation_id_);
}

// This test verifies that worklet animation gets skipped properly.
TEST_F(WorkletAnimationTest, SkipUnchangedAnimations) {
  AttachWorkletAnimation();

  const float start_opacity = .7f;
  const float end_opacity = .3f;
  const double duration = 1.;

  int keyframe_model_id = AddOpacityTransitionToAnimation(
      worklet_animation_.get(), duration, start_opacity, end_opacity, true);

  ScrollTree scroll_tree;
  std::unique_ptr<MutatorInputState> state =
      std::make_unique<MutatorInputState>();

  base::TimeTicks time;
  worklet_animation_->UpdateInputState(state.get(), time, scroll_tree, true);
  std::unique_ptr<AnimationWorkletInput> input =
      state->TakeWorkletState(worklet_animation_id_.worklet_id);
  EXPECT_EQ(input->added_and_updated_animations.size(), 1u);
  EXPECT_EQ(input->updated_animations.size(), 0u);

  state.reset(new MutatorInputState());
  // No update on the input state if input time stays the same.
  worklet_animation_->UpdateInputState(state.get(), time, scroll_tree, true);
  input = state->TakeWorkletState(worklet_animation_id_.worklet_id);
  EXPECT_FALSE(input);

  state.reset(new MutatorInputState());
  // Different input time causes the input state to be updated.
  time += base::TimeDelta::FromSecondsD(0.1);
  worklet_animation_->UpdateInputState(state.get(), time, scroll_tree, true);
  input = state->TakeWorkletState(worklet_animation_id_.worklet_id);
  EXPECT_EQ(input->updated_animations.size(), 1u);

  state.reset(new MutatorInputState());
  // Input state gets updated when the worklet animation is to be removed even
  // the input time doesn't change.
  worklet_animation_->RemoveKeyframeModel(keyframe_model_id);
  worklet_animation_->UpdateInputState(state.get(), time, scroll_tree, true);
  input = state->TakeWorkletState(worklet_animation_id_.worklet_id);
  EXPECT_EQ(input->updated_animations.size(), 0u);
  EXPECT_EQ(input->removed_animations.size(), 1u);
}

}  // namespace

}  // namespace cc
