// 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 "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.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,
                                               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(SkScalar 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 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(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<DecomposedTransform> decomposed_transform =
        std::make_unique<DecomposedTransform>();
    Transform transform = ApplyRemaining(start_offset);
    if (!DecomposeTransform(decomposed_transform.get(), transform))
      return false;
    decomposed_transforms_[start_offset] = std::move(decomposed_transform);
  }
  return true;
}

}  // namespace gfx
