// Copyright (c) 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 "ui/compositor/transform_animation_curve_adapter.h"

#include "base/memory/ptr_util.h"
#include "cc/base/time_util.h"

namespace ui {

namespace {

static cc::TransformOperations WrapTransform(const gfx::Transform& transform) {
  cc::TransformOperations operations;
  operations.AppendMatrix(transform);
  return operations;
}

}  // namespace

TransformAnimationCurveAdapter::TransformAnimationCurveAdapter(
    gfx::Tween::Type tween_type,
    gfx::Transform initial_value,
    gfx::Transform target_value,
    base::TimeDelta duration)
    : tween_type_(tween_type),
      initial_value_(initial_value),
      initial_wrapped_value_(WrapTransform(initial_value)),
      target_value_(target_value),
      target_wrapped_value_(WrapTransform(target_value)),
      duration_(duration) {
  gfx::DecomposeTransform(&decomposed_initial_value_, initial_value);
  gfx::DecomposeTransform(&decomposed_target_value_, target_value);
}

TransformAnimationCurveAdapter::TransformAnimationCurveAdapter(
    const TransformAnimationCurveAdapter& other) = default;

TransformAnimationCurveAdapter::~TransformAnimationCurveAdapter() {
}

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

std::unique_ptr<cc::AnimationCurve> TransformAnimationCurveAdapter::Clone()
    const {
  return base::WrapUnique(new TransformAnimationCurveAdapter(
      tween_type_, initial_value_, target_value_, duration_));
}

cc::TransformOperations TransformAnimationCurveAdapter::GetValue(
    base::TimeDelta t) const {
  if (t >= duration_)
    return target_wrapped_value_;
  if (t <= base::TimeDelta())
    return initial_wrapped_value_;
  double progress = cc::TimeUtil::Divide(t, duration_);

  gfx::DecomposedTransform to_return = gfx::BlendDecomposedTransforms(
      decomposed_target_value_, decomposed_initial_value_,
      gfx::Tween::CalculateValue(tween_type_, progress));

  return WrapTransform(gfx::ComposeTransform(to_return));
}

bool TransformAnimationCurveAdapter::IsTranslation() const {
  return initial_value_.IsIdentityOrTranslation() &&
         target_value_.IsIdentityOrTranslation();
}

bool TransformAnimationCurveAdapter::PreservesAxisAlignment() const {
  return (initial_value_.IsIdentity() ||
          initial_value_.IsScaleOrTranslation()) &&
         (target_value_.IsIdentity() || target_value_.IsScaleOrTranslation());
}

bool TransformAnimationCurveAdapter::AnimationStartScale(
    bool forward_direction,
    float* start_scale) const {
  return false;
}

bool TransformAnimationCurveAdapter::MaximumTargetScale(
    bool forward_direction,
    float* max_scale) const {
  return false;
}

InverseTransformCurveAdapter::InverseTransformCurveAdapter(
    TransformAnimationCurveAdapter base_curve,
    gfx::Transform initial_value,
    base::TimeDelta duration)
    : base_curve_(base_curve),
      initial_value_(initial_value),
      initial_wrapped_value_(WrapTransform(initial_value)),
      duration_(duration) {
  effective_initial_value_ =
      base_curve_.GetValue(base::TimeDelta()).Apply() * initial_value_;
}

InverseTransformCurveAdapter::~InverseTransformCurveAdapter() {
}

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

std::unique_ptr<cc::AnimationCurve> InverseTransformCurveAdapter::Clone()
    const {
  return base::WrapUnique(
      new InverseTransformCurveAdapter(base_curve_, initial_value_, duration_));
}

cc::TransformOperations InverseTransformCurveAdapter::GetValue(
    base::TimeDelta t) const {
  if (t <= base::TimeDelta())
    return initial_wrapped_value_;

  gfx::Transform base_transform = base_curve_.GetValue(t).Apply();
  // Invert base
  gfx::Transform to_return(gfx::Transform::kSkipInitialization);
  bool is_invertible = base_transform.GetInverse(&to_return);
  DCHECK(is_invertible);

  to_return.PreconcatTransform(effective_initial_value_);

  return WrapTransform(to_return);
}

bool InverseTransformCurveAdapter::IsTranslation() const {
  return initial_value_.IsIdentityOrTranslation() &&
         base_curve_.IsTranslation();
}

bool InverseTransformCurveAdapter::PreservesAxisAlignment() const {
  return (initial_value_.IsIdentity() ||
          initial_value_.IsScaleOrTranslation()) &&
         (base_curve_.PreservesAxisAlignment());
}

bool InverseTransformCurveAdapter::AnimationStartScale(
    bool forward_direction,
    float* start_scale) const {
  return false;
}

bool InverseTransformCurveAdapter::MaximumTargetScale(bool forward_direction,
                                                      float* max_scale) const {
  return false;
}

}  // namespace ui
