// 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/animation/keyframed_animation_curve.h"
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/box_f.h"

namespace cc {

namespace {

template <class Keyframe>
void InsertKeyframe(scoped_ptr<Keyframe> keyframe,
                    ScopedPtrVector<Keyframe>& 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[i]->Time()) {
        keyframes.insert(keyframes.begin() + i, keyframe.Pass());
        return;
      }
    }
  }

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

template <class Keyframes>
float GetProgress(double t, size_t i, const Keyframes& keyframes) {
  float progress =
      static_cast<float>((t - keyframes[i]->Time()) /
                         (keyframes[i + 1]->Time() - keyframes[i]->Time()));

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

scoped_ptr<TimingFunction> CloneTimingFunction(
    const TimingFunction* timing_function) {
  DCHECK(timing_function);
  scoped_ptr<AnimationCurve> curve(timing_function->Clone());
  return scoped_ptr<TimingFunction>(
      static_cast<TimingFunction*>(curve.release()));
}

}  // namespace

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

Keyframe::~Keyframe() {}

double Keyframe::Time() const {
  return time_;
}

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

ColorKeyframe::ColorKeyframe(double 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 = CloneTimingFunction(timing_function());
  return ColorKeyframe::Create(Time(), Value(), func.Pass());
}

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

FloatKeyframe::FloatKeyframe(double 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 = CloneTimingFunction(timing_function());
  return FloatKeyframe::Create(Time(), Value(), func.Pass());
}

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

TransformKeyframe::TransformKeyframe(double 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 = CloneTimingFunction(timing_function());
  return TransformKeyframe::Create(Time(), Value(), func.Pass());
}

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

FilterKeyframe::FilterKeyframe(double 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 = CloneTimingFunction(timing_function());
  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_);
}

double 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());
  return to_return.PassAs<AnimationCurve>();
}

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

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

  size_t i = 0;
  for (; i < keyframes_.size() - 1; ++i) {
    if (t < keyframes_[i + 1]->Time())
      break;
  }

  float progress = GetProgress(t, i, keyframes_);

  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_);
}

double 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());
  return to_return.PassAs<AnimationCurve>();
}

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

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

  size_t i = 0;
  for (; i < keyframes_.size() - 1; ++i) {
    if (t < keyframes_[i+1]->Time())
      break;
  }

  float progress = GetProgress(t, i, keyframes_);

  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_);
}

double 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());
  return to_return.PassAs<AnimationCurve>();
}

// Assumes that (*keyframes).front()->Time() < t < (*keyframes).back()-Time().
template<typename ValueType, typename KeyframeType>
static ValueType GetCurveValue(const ScopedPtrVector<KeyframeType>* keyframes,
                               double t) {
  size_t i = 0;
  for (; i < keyframes->size() - 1; ++i) {
    if (t < (*keyframes)[i+1]->Time())
      break;
  }

  double progress = (t - (*keyframes)[i]->Time()) /
                    ((*keyframes)[i+1]->Time() - (*keyframes)[i]->Time());

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

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

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

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

  return GetCurveValue<gfx::Transform, TransformKeyframe>(&keyframes_, t);
}

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;
}

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_);
}

double 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());
  return to_return.PassAs<AnimationCurve>();
}

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

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

  return GetCurveValue<FilterOperations, FilterKeyframe>(&keyframes_, t);
}

}  // namespace cc
