// Copyright 2013 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/transform_operations.h"

#include <stddef.h>

#include <algorithm>

#include "cc/base/math_util.h"
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/geometry/angle_conversions.h"
#include "ui/gfx/geometry/box_f.h"
#include "ui/gfx/geometry/vector3d_f.h"
#include "ui/gfx/transform_util.h"

namespace cc {

TransformOperations::TransformOperations() {}

TransformOperations::TransformOperations(const TransformOperations& other) {
  operations_ = other.operations_;
}

TransformOperations::~TransformOperations() = default;

TransformOperations& TransformOperations::operator=(
    const TransformOperations& other) {
  operations_ = other.operations_;
  return *this;
}

gfx::Transform TransformOperations::Apply() const {
  return ApplyRemaining(0);
}

gfx::Transform TransformOperations::ApplyRemaining(size_t start) const {
  gfx::Transform to_return;
  for (size_t i = start; i < operations_.size(); i++) {
    to_return.PreconcatTransform(operations_[i].matrix);
  }
  return to_return;
}

// TODO(crbug.com/914397): Consolidate blink and cc implementations of transform
// interpolation.
TransformOperations TransformOperations::Blend(const TransformOperations& from,
                                               SkMScalar progress) const {
  TransformOperations to_return;
  if (!BlendInternal(from, progress, &to_return)) {
    // If the matrices cannot be blended, fallback to discrete animation logic.
    // See https://drafts.csswg.org/css-transforms/#matrix-interpolation
    to_return = progress < 0.5 ? from : *this;
  }
  return to_return;
}

bool TransformOperations::BlendedBoundsForBox(const gfx::BoxF& box,
                                              const TransformOperations& from,
                                              SkMScalar min_progress,
                                              SkMScalar max_progress,
                                              gfx::BoxF* bounds) const {
  *bounds = box;

  bool from_identity = from.IsIdentity();
  bool to_identity = IsIdentity();
  if (from_identity && to_identity)
    return true;

  if (!MatchesTypes(from))
    return false;

  size_t num_operations = std::max(from_identity ? 0 : from.operations_.size(),
                                   to_identity ? 0 : operations_.size());

  // Because we are squashing all of the matrices together when applying
  // them to the animation, we must apply them in reverse order when
  // not squashing them.
  for (size_t i = 0; i < num_operations; ++i) {
    size_t operation_index = num_operations - 1 - i;
    gfx::BoxF bounds_for_operation;
    const TransformOperation* from_op =
        from_identity ? nullptr : &from.operations_[operation_index];
    const TransformOperation* to_op =
        to_identity ? nullptr : &operations_[operation_index];
    if (!TransformOperation::BlendedBoundsForBox(*bounds, from_op, to_op,
                                                 min_progress, max_progress,
                                                 &bounds_for_operation)) {
      return false;
    }
    *bounds = bounds_for_operation;
  }

  return true;
}

bool TransformOperations::PreservesAxisAlignment() const {
  for (auto& operation : operations_) {
    switch (operation.type) {
      case TransformOperation::TRANSFORM_OPERATION_IDENTITY:
      case TransformOperation::TRANSFORM_OPERATION_TRANSLATE:
      case TransformOperation::TRANSFORM_OPERATION_SCALE:
        continue;
      case TransformOperation::TRANSFORM_OPERATION_MATRIX:
        if (!operation.matrix.IsIdentity() &&
            !operation.matrix.IsScaleOrTranslation())
          return false;
        continue;
      case TransformOperation::TRANSFORM_OPERATION_ROTATE:
      case TransformOperation::TRANSFORM_OPERATION_SKEW:
      case TransformOperation::TRANSFORM_OPERATION_PERSPECTIVE:
        return false;
    }
  }
  return true;
}

bool TransformOperations::IsTranslation() const {
  for (auto& operation : operations_) {
    switch (operation.type) {
      case TransformOperation::TRANSFORM_OPERATION_IDENTITY:
      case TransformOperation::TRANSFORM_OPERATION_TRANSLATE:
        continue;
      case TransformOperation::TRANSFORM_OPERATION_MATRIX:
        if (!operation.matrix.IsIdentityOrTranslation())
          return false;
        continue;
      case TransformOperation::TRANSFORM_OPERATION_ROTATE:
      case TransformOperation::TRANSFORM_OPERATION_SCALE:
      case TransformOperation::TRANSFORM_OPERATION_SKEW:
      case TransformOperation::TRANSFORM_OPERATION_PERSPECTIVE:
        return false;
    }
  }
  return true;
}

static SkMScalar TanDegrees(double degrees) {
  return SkDoubleToMScalar(std::tan(gfx::DegToRad(degrees)));
}

bool TransformOperations::ScaleComponent(SkMScalar* scale) const {
  SkMScalar operations_scale = 1.f;
  for (auto& operation : operations_) {
    switch (operation.type) {
      case TransformOperation::TRANSFORM_OPERATION_IDENTITY:
      case TransformOperation::TRANSFORM_OPERATION_TRANSLATE:
      case TransformOperation::TRANSFORM_OPERATION_ROTATE:
        continue;
      case TransformOperation::TRANSFORM_OPERATION_MATRIX: {
        if (operation.matrix.HasPerspective())
          return false;
        gfx::Vector2dF scale_components =
            MathUtil::ComputeTransform2dScaleComponents(operation.matrix, 1.f);
        operations_scale *=
            std::max(scale_components.x(), scale_components.y());
        break;
      }
      case TransformOperation::TRANSFORM_OPERATION_SKEW: {
        SkMScalar x_component = TanDegrees(operation.skew.x);
        SkMScalar y_component = TanDegrees(operation.skew.y);
        SkMScalar x_scale = std::sqrt(x_component * x_component + 1);
        SkMScalar y_scale = std::sqrt(y_component * y_component + 1);
        operations_scale *= std::max(x_scale, y_scale);
        break;
      }
      case TransformOperation::TRANSFORM_OPERATION_PERSPECTIVE:
        return false;
      case TransformOperation::TRANSFORM_OPERATION_SCALE:
        operations_scale *= std::max(
            std::abs(operation.scale.x),
            std::max(std::abs(operation.scale.y), std::abs(operation.scale.z)));
    }
  }
  *scale = operations_scale;
  return true;
}

bool TransformOperations::MatchesTypes(const TransformOperations& other) const {
  if (operations_.size() == 0 || other.operations_.size() == 0)
    return true;

  if (operations_.size() != other.operations_.size())
    return false;

  for (size_t i = 0; i < operations_.size(); ++i) {
    if (operations_[i].type != other.operations_[i].type)
      return false;
  }

  return true;
}

size_t TransformOperations::MatchingPrefixLength(
    const TransformOperations& other) const {
  size_t num_operations =
      std::min(operations_.size(), other.operations_.size());
  for (size_t i = 0; i < num_operations; ++i) {
    if (operations_[i].type != other.operations_[i].type) {
      // Remaining operations in each operations list require matrix/matrix3d
      // interpolation.
      return i;
    }
  }
  // If the operations match to the length of the shorter list, then pad its
  // length with the matching identity operations.
  // https://drafts.csswg.org/css-transforms/#transform-function-lists
  return std::max(operations_.size(), other.operations_.size());
}

bool TransformOperations::CanBlendWith(
    const TransformOperations& other) const {
  TransformOperations dummy;
  return BlendInternal(other, 0.5, &dummy);
}

void TransformOperations::AppendTranslate(SkMScalar x,
                                          SkMScalar y,
                                          SkMScalar z) {
  TransformOperation to_add;
  to_add.matrix.Translate3d(x, y, z);
  to_add.type = TransformOperation::TRANSFORM_OPERATION_TRANSLATE;
  to_add.translate.x = x;
  to_add.translate.y = y;
  to_add.translate.z = z;
  operations_.push_back(to_add);
  decomposed_transforms_.clear();
}

void TransformOperations::AppendRotate(SkMScalar x,
                                       SkMScalar y,
                                       SkMScalar z,
                                       SkMScalar degrees) {
  TransformOperation to_add;
  to_add.type = TransformOperation::TRANSFORM_OPERATION_ROTATE;
  to_add.rotate.axis.x = x;
  to_add.rotate.axis.y = y;
  to_add.rotate.axis.z = z;
  to_add.rotate.angle = degrees;
  to_add.Bake();
  operations_.push_back(to_add);
  decomposed_transforms_.clear();
}

void TransformOperations::AppendScale(SkMScalar x, SkMScalar y, SkMScalar z) {
  TransformOperation to_add;
  to_add.type = TransformOperation::TRANSFORM_OPERATION_SCALE;
  to_add.scale.x = x;
  to_add.scale.y = y;
  to_add.scale.z = z;
  to_add.Bake();
  operations_.push_back(to_add);
  decomposed_transforms_.clear();
}

void TransformOperations::AppendSkew(SkMScalar x, SkMScalar y) {
  TransformOperation to_add;
  to_add.type = TransformOperation::TRANSFORM_OPERATION_SKEW;
  to_add.skew.x = x;
  to_add.skew.y = y;
  to_add.Bake();
  operations_.push_back(to_add);
  decomposed_transforms_.clear();
}

void TransformOperations::AppendPerspective(SkMScalar depth) {
  TransformOperation to_add;
  to_add.type = TransformOperation::TRANSFORM_OPERATION_PERSPECTIVE;
  to_add.perspective_depth = depth;
  to_add.Bake();
  operations_.push_back(to_add);
  decomposed_transforms_.clear();
}

void TransformOperations::AppendMatrix(const gfx::Transform& matrix) {
  TransformOperation to_add;
  to_add.matrix = matrix;
  to_add.type = TransformOperation::TRANSFORM_OPERATION_MATRIX;
  operations_.push_back(to_add);
  decomposed_transforms_.clear();
}

void TransformOperations::AppendIdentity() {
  operations_.push_back(TransformOperation());
}

void TransformOperations::Append(const TransformOperation& operation) {
  operations_.push_back(operation);
  decomposed_transforms_.clear();
}

bool TransformOperations::IsIdentity() const {
  for (auto& operation : operations_) {
    if (!operation.IsIdentity())
      return false;
  }
  return true;
}

bool TransformOperations::ApproximatelyEqual(const TransformOperations& other,
                                             SkMScalar tolerance) const {
  if (size() != other.size())
    return false;
  for (size_t i = 0; i < operations_.size(); ++i) {
    if (!operations_[i].ApproximatelyEqual(other.operations_[i], tolerance))
      return false;
  }
  return true;
}

bool TransformOperations::BlendInternal(const TransformOperations& from,
                                        SkMScalar progress,
                                        TransformOperations* result) const {
  bool from_identity = from.IsIdentity();
  bool to_identity = IsIdentity();
  if (from_identity && to_identity)
    return true;

  size_t matching_prefix_length = MatchingPrefixLength(from);
  size_t from_size = from_identity ? 0 : from.operations_.size();
  size_t to_size = to_identity ? 0 : operations_.size();
  size_t num_operations = std::max(from_size, to_size);

  for (size_t i = 0; i < matching_prefix_length; ++i) {
    TransformOperation blended;
    if (!TransformOperation::BlendTransformOperations(
            i >= from_size ? nullptr : &from.operations_[i],
            i >= to_size ? nullptr : &operations_[i], progress, &blended)) {
      return false;
    }
    result->Append(blended);
  }

  if (matching_prefix_length < num_operations) {
    if (!ComputeDecomposedTransform(matching_prefix_length) ||
        !from.ComputeDecomposedTransform(matching_prefix_length)) {
      return false;
    }
    gfx::DecomposedTransform matrix_transform = gfx::BlendDecomposedTransforms(
        *decomposed_transforms_[matching_prefix_length].get(),
        *from.decomposed_transforms_[matching_prefix_length].get(), progress);
    result->AppendMatrix(ComposeTransform(matrix_transform));
  }
  return true;
}

bool TransformOperations::ComputeDecomposedTransform(
    size_t start_offset) const {
  auto it = decomposed_transforms_.find(start_offset);
  if (it == decomposed_transforms_.end()) {
    std::unique_ptr<gfx::DecomposedTransform> decomposed_transform =
        std::make_unique<gfx::DecomposedTransform>();
    gfx::Transform transform = ApplyRemaining(start_offset);
    if (!gfx::DecomposeTransform(decomposed_transform.get(), transform))
      return false;
    decomposed_transforms_[start_offset] = std::move(decomposed_transform);
  }
  return true;
}

}  // namespace cc
