// Copyright 2012 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/test/animation_test_common.h"

#include "base/memory/ptr_util.h"
#include "cc/animation/animation_host.h"
#include "cc/animation/animation_id_provider.h"
#include "cc/animation/animation_player.h"
#include "cc/animation/element_animations.h"
#include "cc/animation/keyframed_animation_curve.h"
#include "cc/animation/scroll_offset_animation_curve.h"
#include "cc/animation/timing_function.h"
#include "cc/animation/transform_operations.h"
#include "cc/base/time_util.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_impl.h"

using cc::Animation;
using cc::AnimationCurve;
using cc::FloatKeyframe;
using cc::KeyframedFloatAnimationCurve;
using cc::KeyframedTransformAnimationCurve;
using cc::TimingFunction;
using cc::TransformKeyframe;

namespace cc {

int AddOpacityTransition(AnimationPlayer* target,
                         double duration,
                         float start_opacity,
                         float end_opacity,
                         bool use_timing_function) {
  std::unique_ptr<KeyframedFloatAnimationCurve> curve(
      KeyframedFloatAnimationCurve::Create());

  std::unique_ptr<TimingFunction> func;
  if (!use_timing_function)
    func = CubicBezierTimingFunction::CreatePreset(
        CubicBezierTimingFunction::EaseType::EASE);
  if (duration > 0.0)
    curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), start_opacity,
                                             std::move(func)));
  curve->AddKeyframe(FloatKeyframe::Create(
      base::TimeDelta::FromSecondsD(duration), end_opacity, nullptr));

  int id = AnimationIdProvider::NextAnimationId();

  std::unique_ptr<Animation> animation(Animation::Create(
      std::move(curve), id, AnimationIdProvider::NextGroupId(),
      TargetProperty::OPACITY));
  animation->set_needs_synchronized_start_time(true);

  target->AddAnimation(std::move(animation));
  return id;
}

int AddAnimatedTransform(AnimationPlayer* target,
                         double duration,
                         TransformOperations start_operations,
                         TransformOperations operations) {
  std::unique_ptr<KeyframedTransformAnimationCurve> curve(
      KeyframedTransformAnimationCurve::Create());

  if (duration > 0.0) {
    curve->AddKeyframe(TransformKeyframe::Create(base::TimeDelta(),
                                                 start_operations, nullptr));
  }

  curve->AddKeyframe(TransformKeyframe::Create(
      base::TimeDelta::FromSecondsD(duration), operations, nullptr));

  int id = AnimationIdProvider::NextAnimationId();

  std::unique_ptr<Animation> animation(Animation::Create(
      std::move(curve), id, AnimationIdProvider::NextGroupId(),
      TargetProperty::TRANSFORM));
  animation->set_needs_synchronized_start_time(true);

  target->AddAnimation(std::move(animation));
  return id;
}

int AddAnimatedTransform(AnimationPlayer* target,
                         double duration,
                         int delta_x,
                         int delta_y) {
  TransformOperations start_operations;
  if (duration > 0.0) {
    start_operations.AppendTranslate(0, 0, 0.0);
  }

  TransformOperations operations;
  operations.AppendTranslate(delta_x, delta_y, 0.0);
  return AddAnimatedTransform(target, duration, start_operations, operations);
}

int AddAnimatedFilter(AnimationPlayer* target,
                      double duration,
                      float start_brightness,
                      float end_brightness) {
  std::unique_ptr<KeyframedFilterAnimationCurve> curve(
      KeyframedFilterAnimationCurve::Create());

  if (duration > 0.0) {
    FilterOperations start_filters;
    start_filters.Append(
        FilterOperation::CreateBrightnessFilter(start_brightness));
    curve->AddKeyframe(
        FilterKeyframe::Create(base::TimeDelta(), start_filters, nullptr));
  }

  FilterOperations filters;
  filters.Append(FilterOperation::CreateBrightnessFilter(end_brightness));
  curve->AddKeyframe(FilterKeyframe::Create(
      base::TimeDelta::FromSecondsD(duration), filters, nullptr));

  int id = AnimationIdProvider::NextAnimationId();

  std::unique_ptr<Animation> animation(Animation::Create(
      std::move(curve), id, AnimationIdProvider::NextGroupId(),
      TargetProperty::FILTER));
  animation->set_needs_synchronized_start_time(true);

  target->AddAnimation(std::move(animation));
  return id;
}

FakeFloatAnimationCurve::FakeFloatAnimationCurve()
    : duration_(base::TimeDelta::FromSecondsD(1.0)) {
}

FakeFloatAnimationCurve::FakeFloatAnimationCurve(double duration)
    : duration_(base::TimeDelta::FromSecondsD(duration)) {
}

FakeFloatAnimationCurve::~FakeFloatAnimationCurve() {}

base::TimeDelta FakeFloatAnimationCurve::Duration() const {
  return duration_;
}

float FakeFloatAnimationCurve::GetValue(base::TimeDelta now) const {
  return 0.0f;
}

std::unique_ptr<AnimationCurve> FakeFloatAnimationCurve::Clone() const {
  return base::WrapUnique(new FakeFloatAnimationCurve);
}

FakeTransformTransition::FakeTransformTransition(double duration)
    : duration_(base::TimeDelta::FromSecondsD(duration)) {
}

FakeTransformTransition::~FakeTransformTransition() {}

base::TimeDelta FakeTransformTransition::Duration() const {
  return duration_;
}

gfx::Transform FakeTransformTransition::GetValue(base::TimeDelta time) const {
  return gfx::Transform();
}

bool FakeTransformTransition::AnimatedBoundsForBox(const gfx::BoxF& box,
                                                   gfx::BoxF* bounds) const {
  return false;
}

bool FakeTransformTransition::IsTranslation() const { return true; }

bool FakeTransformTransition::PreservesAxisAlignment() const {
  return true;
}

bool FakeTransformTransition::AnimationStartScale(bool forward_direction,
                                                  float* start_scale) const {
  *start_scale = 1.f;
  return true;
}

bool FakeTransformTransition::MaximumTargetScale(bool forward_direction,
                                                 float* max_scale) const {
  *max_scale = 1.f;
  return true;
}

std::unique_ptr<AnimationCurve> FakeTransformTransition::Clone() const {
  return base::WrapUnique(new FakeTransformTransition(*this));
}

FakeFloatTransition::FakeFloatTransition(double duration, float from, float to)
    : duration_(base::TimeDelta::FromSecondsD(duration)), from_(from), to_(to) {
}

FakeFloatTransition::~FakeFloatTransition() {}

base::TimeDelta FakeFloatTransition::Duration() const {
  return duration_;
}

float FakeFloatTransition::GetValue(base::TimeDelta time) const {
  double progress = TimeUtil::Divide(time, duration_);
  if (progress >= 1.0)
    progress = 1.0;
  return (1.0 - progress) * from_ + progress * to_;
}

std::unique_ptr<AnimationCurve> FakeFloatTransition::Clone() const {
  return base::WrapUnique(new FakeFloatTransition(*this));
}

int AddScrollOffsetAnimationToPlayer(AnimationPlayer* player,
                                     gfx::ScrollOffset initial_value,
                                     gfx::ScrollOffset target_value,
                                     bool impl_only) {
  std::unique_ptr<ScrollOffsetAnimationCurve> curve(
      ScrollOffsetAnimationCurve::Create(
          target_value, CubicBezierTimingFunction::CreatePreset(
                            CubicBezierTimingFunction::EaseType::EASE_IN_OUT)));
  curve->SetInitialValue(initial_value);

  int id = AnimationIdProvider::NextAnimationId();

  std::unique_ptr<Animation> animation(Animation::Create(
      std::move(curve), id, AnimationIdProvider::NextGroupId(),
      TargetProperty::SCROLL_OFFSET));
  animation->set_is_impl_only(impl_only);

  player->AddAnimation(std::move(animation));

  return id;
}

int AddAnimatedTransformToPlayer(AnimationPlayer* player,
                                 double duration,
                                 int delta_x,
                                 int delta_y) {
  return AddAnimatedTransform(player, duration, delta_x, delta_y);
}

int AddAnimatedTransformToPlayer(AnimationPlayer* player,
                                 double duration,
                                 TransformOperations start_operations,
                                 TransformOperations operations) {
  return AddAnimatedTransform(player, duration, start_operations, operations);
}

int AddOpacityTransitionToPlayer(AnimationPlayer* player,
                                 double duration,
                                 float start_opacity,
                                 float end_opacity,
                                 bool use_timing_function) {
  return AddOpacityTransition(player, duration, start_opacity, end_opacity,
                              use_timing_function);
}

int AddAnimatedFilterToPlayer(AnimationPlayer* player,
                              double duration,
                              float start_brightness,
                              float end_brightness) {
  return AddAnimatedFilter(player, duration, start_brightness, end_brightness);
}

int AddOpacityStepsToPlayer(AnimationPlayer* player,
                            double duration,
                            float start_opacity,
                            float end_opacity,
                            int num_steps) {
  std::unique_ptr<KeyframedFloatAnimationCurve> curve(
      KeyframedFloatAnimationCurve::Create());

  std::unique_ptr<TimingFunction> func = StepsTimingFunction::Create(
      num_steps, StepsTimingFunction::StepPosition::MIDDLE);
  if (duration > 0.0)
    curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), start_opacity,
                                             std::move(func)));
  curve->AddKeyframe(FloatKeyframe::Create(
      base::TimeDelta::FromSecondsD(duration), end_opacity, nullptr));

  int id = AnimationIdProvider::NextAnimationId();

  std::unique_ptr<Animation> animation(Animation::Create(
      std::move(curve), id, AnimationIdProvider::NextGroupId(),
      TargetProperty::OPACITY));
  animation->set_needs_synchronized_start_time(true);

  player->AddAnimation(std::move(animation));
  return id;
}

void AddAnimationToElementWithPlayer(ElementId element_id,
                                     scoped_refptr<AnimationTimeline> timeline,
                                     std::unique_ptr<Animation> animation) {
  scoped_refptr<AnimationPlayer> player =
      AnimationPlayer::Create(AnimationIdProvider::NextPlayerId());
  timeline->AttachPlayer(player);
  player->AttachElement(element_id);
  DCHECK(player->element_animations());
  player->AddAnimation(std::move(animation));
}

void AddAnimationToElementWithExistingPlayer(
    ElementId element_id,
    scoped_refptr<AnimationTimeline> timeline,
    std::unique_ptr<Animation> animation) {
  scoped_refptr<ElementAnimations> element_animations =
      timeline->animation_host()->GetElementAnimationsForElementId(element_id);
  DCHECK(element_animations);
  DCHECK(element_animations->players_list().might_have_observers());
  AnimationPlayer* player = &*element_animations->players_list().begin();
  DCHECK(player);
  player->AddAnimation(std::move(animation));
}

void RemoveAnimationFromElementWithExistingPlayer(
    ElementId element_id,
    scoped_refptr<AnimationTimeline> timeline,
    int animation_id) {
  scoped_refptr<ElementAnimations> element_animations =
      timeline->animation_host()->GetElementAnimationsForElementId(element_id);
  DCHECK(element_animations);
  DCHECK(element_animations->players_list().might_have_observers());
  AnimationPlayer* player = &*element_animations->players_list().begin();
  DCHECK(player);
  player->RemoveAnimation(animation_id);
}

Animation* GetAnimationFromElementWithExistingPlayer(
    ElementId element_id,
    scoped_refptr<AnimationTimeline> timeline,
    int animation_id) {
  scoped_refptr<ElementAnimations> element_animations =
      timeline->animation_host()->GetElementAnimationsForElementId(element_id);
  DCHECK(element_animations);
  DCHECK(element_animations->players_list().might_have_observers());
  AnimationPlayer* player = &*element_animations->players_list().begin();
  DCHECK(player);
  return player->GetAnimationById(animation_id);
}

int AddAnimatedFilterToElementWithPlayer(
    ElementId element_id,
    scoped_refptr<AnimationTimeline> timeline,
    double duration,
    float start_brightness,
    float end_brightness) {
  scoped_refptr<AnimationPlayer> player =
      AnimationPlayer::Create(AnimationIdProvider::NextPlayerId());
  timeline->AttachPlayer(player);
  player->AttachElement(element_id);
  DCHECK(player->element_animations());
  return AddAnimatedFilterToPlayer(player.get(), duration, start_brightness,
                                   end_brightness);
}

int AddAnimatedTransformToElementWithPlayer(
    ElementId element_id,
    scoped_refptr<AnimationTimeline> timeline,
    double duration,
    int delta_x,
    int delta_y) {
  scoped_refptr<AnimationPlayer> player =
      AnimationPlayer::Create(AnimationIdProvider::NextPlayerId());
  timeline->AttachPlayer(player);
  player->AttachElement(element_id);
  DCHECK(player->element_animations());
  return AddAnimatedTransformToPlayer(player.get(), duration, delta_x, delta_y);
}

int AddAnimatedTransformToElementWithPlayer(
    ElementId element_id,
    scoped_refptr<AnimationTimeline> timeline,
    double duration,
    TransformOperations start_operations,
    TransformOperations operations) {
  scoped_refptr<AnimationPlayer> player =
      AnimationPlayer::Create(AnimationIdProvider::NextPlayerId());
  timeline->AttachPlayer(player);
  player->AttachElement(element_id);
  DCHECK(player->element_animations());
  return AddAnimatedTransformToPlayer(player.get(), duration, start_operations,
                                      operations);
}

int AddOpacityTransitionToElementWithPlayer(
    ElementId element_id,
    scoped_refptr<AnimationTimeline> timeline,
    double duration,
    float start_opacity,
    float end_opacity,
    bool use_timing_function) {
  scoped_refptr<AnimationPlayer> player =
      AnimationPlayer::Create(AnimationIdProvider::NextPlayerId());
  timeline->AttachPlayer(player);
  player->AttachElement(element_id);
  DCHECK(player->element_animations());
  return AddOpacityTransitionToPlayer(player.get(), duration, start_opacity,
                                      end_opacity, use_timing_function);
}

}  // namespace cc
