// 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 "ui/gfx/animation/keyframe/keyframe_effect.h"

#include <algorithm>

#include "base/containers/cxx20_erase.h"
#include "ui/gfx/animation/keyframe/animation_curve.h"
#include "ui/gfx/animation/keyframe/keyframed_animation_curve.h"

namespace gfx {

namespace {

static int s_next_keyframe_model_id = 1;
static int s_next_group_id = 1;

void ReverseKeyframeModel(base::TimeTicks monotonic_time,
                          KeyframeModel* keyframe_model) {
  keyframe_model->set_direction(keyframe_model->direction() ==
                                        KeyframeModel::Direction::NORMAL
                                    ? KeyframeModel::Direction::REVERSE
                                    : KeyframeModel::Direction::NORMAL);
  // Our goal here is to reverse the given keyframe_model. That is, if
  // we're 20% of the way through the keyframe_model in the forward direction,
  // we'd like to be 80% of the way of the reversed keyframe model (so it will
  // end quickly).
  //
  // We can modify our "progress" through an animation by modifying the "time
  // offset", a value added to the current time by the animation system before
  // applying any other adjustments.
  //
  // Let our start time be s, our current time be t, and our final time (or
  // duration) be d. After reversing the keyframe_model, we would like to start
  // sampling from d - t as depicted below.
  //
  //  Forward:
  //  s    t                         d
  //  |----|-------------------------|
  //
  //  Reversed:
  //  s                         t    d
  //  |----|--------------------|----|
  //       -----time-offset----->
  //
  // Now, if we let o represent our desired offset, we need to ensure that
  //   t = d - (o + t)
  //
  // That is, sampling at the current time in either the forward or reverse
  // curves must result in the same value, otherwise we'll get jank.
  //
  // This implies that,
  //   0 = d - o - 2t
  //   o = d - 2t
  //
  // Now if there was a previous offset, we must adjust d by that offset before
  // performing this computation, so it becomes d - o_old - 2t:
  keyframe_model->set_time_offset(
      keyframe_model->curve()->Duration() - keyframe_model->time_offset() -
      (2 * (monotonic_time - keyframe_model->start_time())));
}

std::unique_ptr<CubicBezierTimingFunction> CreateTransitionTimingFunction() {
  return CubicBezierTimingFunction::CreatePreset(
      CubicBezierTimingFunction::EaseType::EASE);
}

base::TimeDelta GetStartTime(KeyframeModel* keyframe_model) {
  if (keyframe_model->direction() == KeyframeModel::Direction::NORMAL) {
    return base::TimeDelta();
  }
  return keyframe_model->curve()->Duration();
}

base::TimeDelta GetEndTime(KeyframeModel* keyframe_model) {
  if (keyframe_model->direction() == KeyframeModel::Direction::REVERSE) {
    return base::TimeDelta();
  }
  return keyframe_model->curve()->Duration();
}

template <typename ValueType>
void TransitionValueTo(KeyframeEffect* animator,
                       typename AnimationTraits<ValueType>::TargetType* target,
                       base::TimeTicks monotonic_time,
                       int target_property,
                       const ValueType& from,
                       const ValueType& to) {
  DCHECK(target);

  if (animator->transition().target_properties.find(target_property) ==
      animator->transition().target_properties.end()) {
    AnimationTraits<ValueType>::OnValueAnimated(target, to, target_property);
    return;
  }

  KeyframeModel* running_keyframe_model =
      animator->GetRunningKeyframeModelForProperty(target_property);

  ValueType effective_current = from;

  if (running_keyframe_model) {
    const auto* curve = AnimationTraits<ValueType>::ToDerivedCurve(
        running_keyframe_model->curve());

    if (running_keyframe_model->IsFinishedAt(monotonic_time)) {
      effective_current = curve->GetValue(GetEndTime(running_keyframe_model));
    } else {
      if (SufficientlyEqual(
              to, curve->GetValue(GetEndTime(running_keyframe_model)))) {
        return;
      }
      if (SufficientlyEqual(
              to, curve->GetValue(GetStartTime(running_keyframe_model)))) {
        ReverseKeyframeModel(monotonic_time, running_keyframe_model);
        return;
      }
    }
  } else if (SufficientlyEqual(to, from)) {
    return;
  }

  animator->RemoveKeyframeModels(target_property);

  std::unique_ptr<typename AnimationTraits<ValueType>::KeyframedCurveType>
      curve(AnimationTraits<ValueType>::KeyframedCurveType::Create());

  curve->AddKeyframe(AnimationTraits<ValueType>::KeyframeType::Create(
      base::TimeDelta(), effective_current, CreateTransitionTimingFunction()));

  curve->AddKeyframe(AnimationTraits<ValueType>::KeyframeType::Create(
      animator->transition().duration, to, CreateTransitionTimingFunction()));

  curve->set_target(target);

  animator->AddKeyframeModel(KeyframeModel::Create(
      std::move(curve), KeyframeEffect::GetNextKeyframeModelId(),
      target_property));
}

}  // namespace

int KeyframeEffect::GetNextKeyframeModelId() {
  return s_next_keyframe_model_id++;
}

int KeyframeEffect::GetNextGroupId() {
  return s_next_group_id++;
}

KeyframeEffect::KeyframeEffect() = default;
KeyframeEffect::KeyframeEffect(KeyframeEffect&&) = default;
KeyframeEffect::~KeyframeEffect() = default;

void KeyframeEffect::AddKeyframeModel(
    std::unique_ptr<KeyframeModel> keyframe_model) {
  keyframe_models_.push_back(std::move(keyframe_model));
}

void KeyframeEffect::RemoveKeyframeModel(int keyframe_model_id) {
  // Since we want to use the KeyframeModels that we're going to remove, we
  // need to use a stable_partition here instead of remove_if. remove_if leaves
  // the removed items in an unspecified state.
  auto keyframe_models_to_remove = std::stable_partition(
      keyframe_models_.begin(), keyframe_models_.end(),
      [keyframe_model_id](
          const std::unique_ptr<gfx::KeyframeModel>& keyframe_model) {
        return keyframe_model->id() != keyframe_model_id;
      });

  RemoveKeyframeModelRange(keyframe_models_to_remove, keyframe_models_.end());
}

void KeyframeEffect::RemoveKeyframeModels(int target_property) {
  auto keyframe_models_to_remove = std::stable_partition(
      keyframe_models_.begin(), keyframe_models_.end(),
      [target_property](
          const std::unique_ptr<gfx::KeyframeModel>& keyframe_model) {
        return keyframe_model->TargetProperty() != target_property;
      });
  RemoveKeyframeModelRange(keyframe_models_to_remove, keyframe_models_.end());
}

void KeyframeEffect::RemoveAllKeyframeModels() {
  RemoveKeyframeModelRange(keyframe_models_.begin(), keyframe_models_.end());
}

void KeyframeEffect::Tick(base::TimeTicks monotonic_time) {
  TickInternal(monotonic_time, true);
}

void KeyframeEffect::RemoveKeyframeModelRange(
    typename KeyframeModels::iterator to_remove_begin,
    typename KeyframeModels::iterator to_remove_end) {
  keyframe_models_.erase(to_remove_begin, to_remove_end);
}

void KeyframeEffect::TickKeyframeModel(base::TimeTicks monotonic_time,
                                       KeyframeModel* keyframe_model) {
  if ((keyframe_model->run_state() != KeyframeModel::STARTING &&
       keyframe_model->run_state() != KeyframeModel::RUNNING &&
       keyframe_model->run_state() != KeyframeModel::PAUSED) ||
      !keyframe_model->HasActiveTime(monotonic_time)) {
    return;
  }

  AnimationCurve* curve = keyframe_model->curve();
  base::TimeDelta trimmed =
      keyframe_model->TrimTimeToCurrentIteration(monotonic_time);
  curve->Tick(trimmed, keyframe_model->TargetProperty(), keyframe_model);
}

void KeyframeEffect::TickInternal(base::TimeTicks monotonic_time,
                                  bool include_infinite_animations) {
  StartKeyframeModels(monotonic_time, include_infinite_animations);

  for (auto& keyframe_model : keyframe_models_) {
    if (!include_infinite_animations &&
        keyframe_model->iterations() == std::numeric_limits<double>::infinity())
      continue;
    TickKeyframeModel(monotonic_time, keyframe_model.get());
  }

  // Remove finished keyframe_models.
  base::EraseIf(
      keyframe_models_,
      [monotonic_time](const std::unique_ptr<KeyframeModel>& keyframe_model) {
        return !keyframe_model->is_finished() &&
               keyframe_model->IsFinishedAt(monotonic_time);
      });

  StartKeyframeModels(monotonic_time, include_infinite_animations);
}

void KeyframeEffect::FinishAll() {
  base::TimeTicks now = base::TimeTicks::Now();
  const bool include_infinite_animations = false;
  TickInternal(now, include_infinite_animations);
  TickInternal(base::TimeTicks::Max(), include_infinite_animations);
#ifndef NDEBUG
  for (auto& keyframe_model : keyframe_models_) {
    DCHECK_EQ(std::numeric_limits<double>::infinity(),
              keyframe_model->iterations());
  }
#endif
}

void KeyframeEffect::SetTransitionedProperties(
    const std::set<int>& properties) {
  transition_.target_properties = properties;
}

void KeyframeEffect::SetTransitionDuration(base::TimeDelta delta) {
  transition_.duration = delta;
}

void KeyframeEffect::TransitionFloatTo(FloatAnimationCurve::Target* target,
                                       base::TimeTicks monotonic_time,
                                       int target_property,
                                       float from,
                                       float to) {
  TransitionValueTo<float>(this, target, monotonic_time, target_property, from,
                           to);
}

void KeyframeEffect::TransitionTransformOperationsTo(
    TransformAnimationCurve::Target* target,
    base::TimeTicks monotonic_time,
    int target_property,
    const gfx::TransformOperations& from,
    const gfx::TransformOperations& to) {
  TransitionValueTo<gfx::TransformOperations>(this, target, monotonic_time,
                                              target_property, from, to);
}

void KeyframeEffect::TransitionSizeTo(SizeAnimationCurve::Target* target,
                                      base::TimeTicks monotonic_time,
                                      int target_property,
                                      const gfx::SizeF& from,
                                      const gfx::SizeF& to) {
  TransitionValueTo<gfx::SizeF>(this, target, monotonic_time, target_property,
                                from, to);
}

void KeyframeEffect::TransitionColorTo(ColorAnimationCurve::Target* target,
                                       base::TimeTicks monotonic_time,
                                       int target_property,
                                       SkColor from,
                                       SkColor to) {
  TransitionValueTo<SkColor>(this, target, monotonic_time, target_property,
                             from, to);
}

bool KeyframeEffect::IsAnimatingProperty(int property) const {
  for (auto& keyframe_model : keyframe_models_) {
    if (keyframe_model->TargetProperty() == property)
      return true;
  }
  return false;
}

bool KeyframeEffect::IsAnimating() const {
  return !keyframe_models_.empty();
}

float KeyframeEffect::GetTargetFloatValue(int target_property,
                                          float default_value) const {
  return GetTargetValue<float>(target_property, default_value);
}

gfx::TransformOperations KeyframeEffect::GetTargetTransformOperationsValue(
    int target_property,
    const gfx::TransformOperations& default_value) const {
  return GetTargetValue<gfx::TransformOperations>(target_property,
                                                  default_value);
}

gfx::SizeF KeyframeEffect::GetTargetSizeValue(
    int target_property,
    const gfx::SizeF& default_value) const {
  return GetTargetValue<gfx::SizeF>(target_property, default_value);
}

SkColor KeyframeEffect::GetTargetColorValue(int target_property,
                                            SkColor default_value) const {
  return GetTargetValue<SkColor>(target_property, default_value);
}

void KeyframeEffect::StartKeyframeModels(base::TimeTicks monotonic_time,
                                         bool include_infinite_animations) {
  TargetProperties animated_properties;
  for (auto& keyframe_model : keyframe_models_) {
    if (!include_infinite_animations &&
        keyframe_model->iterations() == std::numeric_limits<double>::infinity())
      continue;
    if (keyframe_model->run_state() == KeyframeModel::RUNNING ||
        keyframe_model->run_state() == KeyframeModel::PAUSED) {
      animated_properties[keyframe_model->TargetProperty()] = true;
    }
  }
  for (auto& keyframe_model : keyframe_models_) {
    if (!include_infinite_animations &&
        keyframe_model->iterations() == std::numeric_limits<double>::infinity())
      continue;
    if (!animated_properties[keyframe_model->TargetProperty()] &&
        keyframe_model->run_state() ==
            KeyframeModel::WAITING_FOR_TARGET_AVAILABILITY) {
      animated_properties[keyframe_model->TargetProperty()] = true;
      keyframe_model->SetRunState(KeyframeModel::RUNNING, monotonic_time);
      keyframe_model->set_start_time(monotonic_time);
    }
  }
}

KeyframeModel* KeyframeEffect::GetRunningKeyframeModelForProperty(
    int target_property) const {
  for (auto& keyframe_model : keyframe_models_) {
    if ((keyframe_model->run_state() == KeyframeModel::RUNNING ||
         keyframe_model->run_state() == KeyframeModel::PAUSED) &&
        keyframe_model->TargetProperty() == target_property) {
      return keyframe_model.get();
    }
  }
  return nullptr;
}

KeyframeModel* KeyframeEffect::GetKeyframeModel(int target_property) const {
  for (size_t i = 0; i < keyframe_models().size(); ++i) {
    size_t index = keyframe_models().size() - i - 1;
    if (keyframe_models_[index]->TargetProperty() == target_property)
      return keyframe_models_[index].get();
  }
  return nullptr;
}

KeyframeModel* KeyframeEffect::GetKeyframeModelById(int id) const {
  for (auto& keyframe_model : keyframe_models())
    if (keyframe_model->id() == id)
      return keyframe_model.get();
  return nullptr;
}

template <typename ValueType>
ValueType KeyframeEffect::GetTargetValue(int target_property,
                                         const ValueType& default_value) const {
  KeyframeModel* running_keyframe_model = GetKeyframeModel(target_property);
  if (!running_keyframe_model) {
    return default_value;
  }
  const auto* curve = AnimationTraits<ValueType>::ToDerivedCurve(
      running_keyframe_model->curve());
  return curve->GetValue(GetEndTime(running_keyframe_model));
}

}  // namespace gfx
