// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/gfx/geometry/transform_operations.h"

#include <stddef.h>

#include <algorithm>
#include <utility>

#include "ui/gfx/geometry/angle_conversions.h"
#include "ui/gfx/geometry/box_f.h"
#include "ui/gfx/geometry/transform_util.h"
#include "ui/gfx/geometry/vector3d_f.h"

namespace gfx {

TransformOperations::TransformOperations() = default;

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

TransformOperations::~TransformOperations() = default;

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

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

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

// TODO(crbug.com/914397): Consolidate blink and cc implementations of transform
// interpolation.
TransformOperations TransformOperations::Blend(const TransformOperations& from,
                                               SkScalar 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 BoxF& box,
                                              const TransformOperations& from,
                                              SkScalar min_progress,
                                              SkScalar max_progress,
                                              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;
    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_SKEWX:
      case TransformOperation::TRANSFORM_OPERATION_SKEWY:
      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_SKEWX:
      case TransformOperation::TRANSFORM_OPERATION_SKEWY:
      case TransformOperation::TRANSFORM_OPERATION_SKEW:
      case TransformOperation::TRANSFORM_OPERATION_PERSPECTIVE:
        return false;
    }
  }
  return true;
}

static SkScalar TanDegrees(double degrees) {
  return SkDoubleToScalar(std::tan(DegToRad(degrees)));
}

bool TransformOperations::ScaleComponent(SkScalar* scale) const {
  SkScalar 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;
        Vector2dF scale_components =
            ComputeTransform2dScaleComponents(operation.matrix, 1.f);
        operations_scale *=
            std::max(scale_components.x(), scale_components.y());
        break;
      }
      case TransformOperation::TRANSFORM_OPERATION_SKEWX:
      case TransformOperation::TRANSFORM_OPERATION_SKEWY:
      case TransformOperation::TRANSFORM_OPERATION_SKEW: {
        SkScalar x_component = TanDegrees(operation.skew.x);
        SkScalar y_component = TanDegrees(operation.skew.y);
        SkScalar x_scale = std::sqrt(x_component * x_component + 1);
        SkScalar 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(SkScalar x, SkScalar y, SkScalar 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(SkScalar x,
                                       SkScalar y,
                                       SkScalar z,
                                       SkScalar 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(SkScalar x, SkScalar y, SkScalar 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::AppendSkewX(SkScalar x) {
  TransformOperation to_add;
  to_add.type = TransformOperation::TRANSFORM_OPERATION_SKEWX;
  to_add.skew.x = x;
  to_add.skew.y = 0;
  to_add.Bake();
  operations_.push_back(to_add);
  decomposed_transforms_.clear();
}

void TransformOperations::AppendSkewY(SkScalar y) {
  TransformOperation to_add;
  to_add.type = TransformOperation::TRANSFORM_OPERATION_SKEWY;
  to_add.skew.x = 0;
  to_add.skew.y = y;
  to_add.Bake();
  operations_.push_back(to_add);
  decomposed_transforms_.clear();
}

void TransformOperations::AppendSkew(SkScalar x, SkScalar 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(absl::optional<SkScalar> depth) {
  TransformOperation to_add;
  to_add.type = TransformOperation::TRANSFORM_OPERATION_PERSPECTIVE;
  if (depth) {
    DCHECK_GE(*depth, 1.0f);
    to_add.perspective_m43 = -1.0f / *depth;
  } else {
    to_add.perspective_m43 = 0.0f;
  }
  to_add.Bake();
  operations_.push_back(to_add);
  decomposed_transforms_.clear();
}

void TransformOperations::AppendMatrix(const 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_.emplace_back();
}

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,
                                             SkScalar 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,
                                        SkScalar 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;
    }
    DecomposedTransform matrix_transform = BlendDecomposedTransforms(
        *decomposed_transforms_[matching_prefix_length].get(),
        *from.decomposed_transforms_[matching_prefix_length].get(), progress);
    result->AppendMatrix(Transform::Compose(matrix_transform));
  }
  return true;
}

bool TransformOperations::ComputeDecomposedTransform(
    size_t start_offset) const {
  auto it = decomposed_transforms_.find(start_offset);
  if (it == decomposed_transforms_.end()) {
    Transform transform = ApplyRemaining(start_offset);
    if (absl::optional<DecomposedTransform> decomp = transform.Decompose()) {
      decomposed_transforms_[start_offset] =
          std::make_unique<DecomposedTransform>(*decomp);
    } else {
      return false;
    }
  }
  return true;
}

}  // namespace gfx
