// 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 <algorithm>

#include "cc/animation/keyframed_animation_curve.h"
#include "cc/base/time_util.h"
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/geometry/box_f.h"

namespace cc {

namespace {

template <class KeyframeType>
void InsertKeyframe(scoped_ptr<KeyframeType> keyframe,
                    ScopedPtrVector<KeyframeType>* keyframes) {
  // Usually, the keyframes will be added in order, so this loop would be
  // unnecessary and we should skip it if possible.
  if (!keyframes->empty() && keyframe->Time() < keyframes->back()->Time()) {
    for (size_t i = 0; i < keyframes->size(); ++i) {
      if (keyframe->Time() < keyframes->at(i)->Time()) {
        keyframes->insert(keyframes->begin() + i, keyframe.Pass());
        return;
      }
    }
  }

  keyframes->push_back(keyframe.Pass());
}

template <typename KeyframeType>
base::TimeDelta TransformedAnimationTime(
    const ScopedPtrVector<KeyframeType>& keyframes,
    const scoped_ptr<TimingFunction>& timing_function,
    base::TimeDelta time) {
  if (timing_function) {
    base::TimeDelta start_time = keyframes.front()->Time();
    base::TimeDelta duration =
        keyframes.back()->Time() - keyframes.front()->Time();
    double progress = TimeUtil::Divide(time - start_time, duration);

    time = TimeUtil::Scale(duration, timing_function->GetValue(progress)) +
           start_time;
  }

  return time;
}

template <typename KeyframeType>
size_t GetActiveKeyframe(const ScopedPtrVector<KeyframeType>& keyframes,
                         base::TimeDelta time) {
  DCHECK_GE(keyframes.size(), 2ul);
  size_t i = 0;
  for (; i < keyframes.size() - 2; ++i) {  // Last keyframe is never active.
    if (time < keyframes[i + 1]->Time())
      break;
  }

  return i;
}

template <typename KeyframeType>
double TransformedKeyframeProgress(
    const ScopedPtrVector<KeyframeType>& keyframes,
    base::TimeDelta time,
    size_t i) {
  double progress =
      TimeUtil::Divide(time - keyframes[i]->Time(),
                       keyframes[i + 1]->Time() - keyframes[i]->Time());

  if (keyframes[i]->timing_function()) {
    progress = keyframes[i]->timing_function()->GetValue(progress);
  }

  return progress;
}

}  // namespace

Keyframe::Keyframe(base::TimeDelta time,
                   scoped_ptr<TimingFunction> timing_function)
    : time_(time), timing_function_(timing_function.Pass()) {
}

Keyframe::~Keyframe() {}

base::TimeDelta Keyframe::Time() const {
  return time_;
}

scoped_ptr<ColorKeyframe> ColorKeyframe::Create(
    base::TimeDelta time,
    SkColor value,
    scoped_ptr<TimingFunction> timing_function) {
  return make_scoped_ptr(
      new ColorKeyframe(time, value, timing_function.Pass()));
}

ColorKeyframe::ColorKeyframe(base::TimeDelta time,
                             SkColor value,
                             scoped_ptr<TimingFunction> timing_function)
    : Keyframe(time, timing_function.Pass()), value_(value) {
}

ColorKeyframe::~ColorKeyframe() {}

SkColor ColorKeyframe::Value() const { return value_; }

scoped_ptr<ColorKeyframe> ColorKeyframe::Clone() const {
  scoped_ptr<TimingFunction> func;
  if (timing_function())
    func = timing_function()->Clone();
  return ColorKeyframe::Create(Time(), Value(), func.Pass());
}

scoped_ptr<FloatKeyframe> FloatKeyframe::Create(
    base::TimeDelta time,
    float value,
    scoped_ptr<TimingFunction> timing_function) {
  return make_scoped_ptr(
      new FloatKeyframe(time, value, timing_function.Pass()));
}

FloatKeyframe::FloatKeyframe(base::TimeDelta time,
                             float value,
                             scoped_ptr<TimingFunction> timing_function)
    : Keyframe(time, timing_function.Pass()), value_(value) {
}

FloatKeyframe::~FloatKeyframe() {}

float FloatKeyframe::Value() const {
  return value_;
}

scoped_ptr<FloatKeyframe> FloatKeyframe::Clone() const {
  scoped_ptr<TimingFunction> func;
  if (timing_function())
    func = timing_function()->Clone();
  return FloatKeyframe::Create(Time(), Value(), func.Pass());
}

scoped_ptr<TransformKeyframe> TransformKeyframe::Create(
    base::TimeDelta time,
    const TransformOperations& value,
    scoped_ptr<TimingFunction> timing_function) {
  return make_scoped_ptr(
      new TransformKeyframe(time, value, timing_function.Pass()));
}

TransformKeyframe::TransformKeyframe(base::TimeDelta time,
                                     const TransformOperations& value,
                                     scoped_ptr<TimingFunction> timing_function)
    : Keyframe(time, timing_function.Pass()), value_(value) {
}

TransformKeyframe::~TransformKeyframe() {}

const TransformOperations& TransformKeyframe::Value() const {
  return value_;
}

scoped_ptr<TransformKeyframe> TransformKeyframe::Clone() const {
  scoped_ptr<TimingFunction> func;
  if (timing_function())
    func = timing_function()->Clone();
  return TransformKeyframe::Create(Time(), Value(), func.Pass());
}

scoped_ptr<FilterKeyframe> FilterKeyframe::Create(
    base::TimeDelta time,
    const FilterOperations& value,
    scoped_ptr<TimingFunction> timing_function) {
  return make_scoped_ptr(
      new FilterKeyframe(time, value, timing_function.Pass()));
}

FilterKeyframe::FilterKeyframe(base::TimeDelta time,
                               const FilterOperations& value,
                               scoped_ptr<TimingFunction> timing_function)
    : Keyframe(time, timing_function.Pass()), value_(value) {
}

FilterKeyframe::~FilterKeyframe() {}

const FilterOperations& FilterKeyframe::Value() const {
  return value_;
}

scoped_ptr<FilterKeyframe> FilterKeyframe::Clone() const {
  scoped_ptr<TimingFunction> func;
  if (timing_function())
    func = timing_function()->Clone();
  return FilterKeyframe::Create(Time(), Value(), func.Pass());
}

scoped_ptr<KeyframedColorAnimationCurve> KeyframedColorAnimationCurve::
    Create() {
  return make_scoped_ptr(new KeyframedColorAnimationCurve);
}

KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {}

KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {}

void KeyframedColorAnimationCurve::AddKeyframe(
    scoped_ptr<ColorKeyframe> keyframe) {
  InsertKeyframe(keyframe.Pass(), &keyframes_);
}

base::TimeDelta KeyframedColorAnimationCurve::Duration() const {
  return keyframes_.back()->Time() - keyframes_.front()->Time();
}

scoped_ptr<AnimationCurve> KeyframedColorAnimationCurve::Clone() const {
  scoped_ptr<KeyframedColorAnimationCurve> to_return =
      KeyframedColorAnimationCurve::Create();
  for (size_t i = 0; i < keyframes_.size(); ++i)
    to_return->AddKeyframe(keyframes_[i]->Clone());

  if (timing_function_)
    to_return->SetTimingFunction(timing_function_->Clone());

  return to_return.Pass();
}

SkColor KeyframedColorAnimationCurve::GetValue(base::TimeDelta t) const {
  if (t <= keyframes_.front()->Time())
    return keyframes_.front()->Value();

  if (t >= keyframes_.back()->Time())
    return keyframes_.back()->Value();

  t = TransformedAnimationTime(keyframes_, timing_function_, t);
  size_t i = GetActiveKeyframe(keyframes_, t);
  double progress = TransformedKeyframeProgress(keyframes_, t, i);

  return gfx::Tween::ColorValueBetween(
      progress, keyframes_[i]->Value(), keyframes_[i + 1]->Value());
}

// KeyframedFloatAnimationCurve

scoped_ptr<KeyframedFloatAnimationCurve> KeyframedFloatAnimationCurve::
    Create() {
  return make_scoped_ptr(new KeyframedFloatAnimationCurve);
}

KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {}

KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {}

void KeyframedFloatAnimationCurve::AddKeyframe(
    scoped_ptr<FloatKeyframe> keyframe) {
  InsertKeyframe(keyframe.Pass(), &keyframes_);
}

base::TimeDelta KeyframedFloatAnimationCurve::Duration() const {
  return keyframes_.back()->Time() - keyframes_.front()->Time();
}

scoped_ptr<AnimationCurve> KeyframedFloatAnimationCurve::Clone() const {
  scoped_ptr<KeyframedFloatAnimationCurve> to_return =
      KeyframedFloatAnimationCurve::Create();
  for (size_t i = 0; i < keyframes_.size(); ++i)
    to_return->AddKeyframe(keyframes_[i]->Clone());

  if (timing_function_)
    to_return->SetTimingFunction(timing_function_->Clone());

  return to_return.Pass();
}

float KeyframedFloatAnimationCurve::GetValue(base::TimeDelta t) const {
  if (t <= keyframes_.front()->Time())
    return keyframes_.front()->Value();

  if (t >= keyframes_.back()->Time())
    return keyframes_.back()->Value();

  t = TransformedAnimationTime(keyframes_, timing_function_, t);
  size_t i = GetActiveKeyframe(keyframes_, t);
  double progress = TransformedKeyframeProgress(keyframes_, t, i);

  return keyframes_[i]->Value() +
      (keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress;
}

scoped_ptr<KeyframedTransformAnimationCurve> KeyframedTransformAnimationCurve::
    Create() {
  return make_scoped_ptr(new KeyframedTransformAnimationCurve);
}

KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {}

KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {}

void KeyframedTransformAnimationCurve::AddKeyframe(
    scoped_ptr<TransformKeyframe> keyframe) {
  InsertKeyframe(keyframe.Pass(), &keyframes_);
}

base::TimeDelta KeyframedTransformAnimationCurve::Duration() const {
  return keyframes_.back()->Time() - keyframes_.front()->Time();
}

scoped_ptr<AnimationCurve> KeyframedTransformAnimationCurve::Clone() const {
  scoped_ptr<KeyframedTransformAnimationCurve> to_return =
      KeyframedTransformAnimationCurve::Create();
  for (size_t i = 0; i < keyframes_.size(); ++i)
    to_return->AddKeyframe(keyframes_[i]->Clone());

  if (timing_function_)
    to_return->SetTimingFunction(timing_function_->Clone());

  return to_return.Pass();
}

gfx::Transform KeyframedTransformAnimationCurve::GetValue(
    base::TimeDelta t) const {
  if (t <= keyframes_.front()->Time())
    return keyframes_.front()->Value().Apply();

  if (t >= keyframes_.back()->Time())
    return keyframes_.back()->Value().Apply();

  t = TransformedAnimationTime(keyframes_, timing_function_, t);
  size_t i = GetActiveKeyframe(keyframes_, t);
  double progress = TransformedKeyframeProgress(keyframes_, t, i);

  return keyframes_[i + 1]->Value().Blend(keyframes_[i]->Value(), progress);
}

bool KeyframedTransformAnimationCurve::AnimatedBoundsForBox(
    const gfx::BoxF& box,
    gfx::BoxF* bounds) const {
  DCHECK_GE(keyframes_.size(), 2ul);
  *bounds = gfx::BoxF();
  for (size_t i = 0; i < keyframes_.size() - 1; ++i) {
    gfx::BoxF bounds_for_step;
    float min_progress = 0.0;
    float max_progress = 1.0;
    if (keyframes_[i]->timing_function())
      keyframes_[i]->timing_function()->Range(&min_progress, &max_progress);
    if (!keyframes_[i+1]->Value().BlendedBoundsForBox(box,
                                                      keyframes_[i]->Value(),
                                                      min_progress,
                                                      max_progress,
                                                      &bounds_for_step))
      return false;
    bounds->Union(bounds_for_step);
  }
  return true;
}

bool KeyframedTransformAnimationCurve::AffectsScale() const {
  for (size_t i = 0; i < keyframes_.size(); ++i) {
    if (keyframes_[i]->Value().AffectsScale())
      return true;
  }
  return false;
}

bool KeyframedTransformAnimationCurve::PreservesAxisAlignment() const {
  for (size_t i = 0; i < keyframes_.size(); ++i) {
    if (!keyframes_[i]->Value().PreservesAxisAlignment())
      return false;
  }
  return true;
}

bool KeyframedTransformAnimationCurve::IsTranslation() const {
  for (size_t i = 0; i < keyframes_.size(); ++i) {
    if (!keyframes_[i]->Value().IsTranslation() &&
        !keyframes_[i]->Value().IsIdentity())
      return false;
  }
  return true;
}

bool KeyframedTransformAnimationCurve::MaximumTargetScale(
    bool forward_direction,
    float* max_scale) const {
  DCHECK_GE(keyframes_.size(), 2ul);
  *max_scale = 0.f;

  // If |forward_direction| is true, then skip the first frame, otherwise
  // skip the last frame, since that is the original position in the animation.
  size_t start = 1;
  size_t end = keyframes_.size();
  if (!forward_direction) {
    --start;
    --end;
  }

  for (size_t i = start; i < end; ++i) {
    gfx::Vector3dF target_scale_for_segment;
    if (!keyframes_[i]->Value().ScaleComponent(&target_scale_for_segment))
      return false;
    float max_scale_for_segment =
        fmax(std::abs(target_scale_for_segment.x()),
             fmax(std::abs(target_scale_for_segment.y()),
                  std::abs(target_scale_for_segment.z())));
    *max_scale = fmax(*max_scale, max_scale_for_segment);
  }
  return true;
}

scoped_ptr<KeyframedFilterAnimationCurve> KeyframedFilterAnimationCurve::
    Create() {
  return make_scoped_ptr(new KeyframedFilterAnimationCurve);
}

KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {}

KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {}

void KeyframedFilterAnimationCurve::AddKeyframe(
    scoped_ptr<FilterKeyframe> keyframe) {
  InsertKeyframe(keyframe.Pass(), &keyframes_);
}

base::TimeDelta KeyframedFilterAnimationCurve::Duration() const {
  return keyframes_.back()->Time() - keyframes_.front()->Time();
}

scoped_ptr<AnimationCurve> KeyframedFilterAnimationCurve::Clone() const {
  scoped_ptr<KeyframedFilterAnimationCurve> to_return =
      KeyframedFilterAnimationCurve::Create();
  for (size_t i = 0; i < keyframes_.size(); ++i)
    to_return->AddKeyframe(keyframes_[i]->Clone());

  if (timing_function_)
    to_return->SetTimingFunction(timing_function_->Clone());

  return to_return.Pass();
}

FilterOperations KeyframedFilterAnimationCurve::GetValue(
    base::TimeDelta t) const {
  if (t <= keyframes_.front()->Time())
    return keyframes_.front()->Value();

  if (t >= keyframes_.back()->Time())
    return keyframes_.back()->Value();

  t = TransformedAnimationTime(keyframes_, timing_function_, t);
  size_t i = GetActiveKeyframe(keyframes_, t);
  double progress = TransformedKeyframeProgress(keyframes_, t, i);

  return keyframes_[i + 1]->Value().Blend(keyframes_[i]->Value(), progress);
}

bool KeyframedFilterAnimationCurve::HasFilterThatMovesPixels() const {
  for (size_t i = 0; i < keyframes_.size(); ++i) {
    if (keyframes_[i]->Value().HasFilterThatMovesPixels()) {
      return true;
    }
  }
  return false;
}

}  // namespace cc
