/*
 * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "sky/engine/platform/transforms/TransformOperations.h"

#include <algorithm>
#include "sky/engine/platform/animation/AnimationUtilities.h"
#include "sky/engine/platform/geometry/FloatBox.h"
#include "sky/engine/platform/transforms/IdentityTransformOperation.h"
#include "sky/engine/platform/transforms/InterpolatedTransformOperation.h"
#include "sky/engine/platform/transforms/RotateTransformOperation.h"

namespace blink {

TransformOperations::TransformOperations(bool makeIdentity)
{
    if (makeIdentity)
        m_operations.append(IdentityTransformOperation::create());
}

bool TransformOperations::operator==(const TransformOperations& o) const
{
    if (m_operations.size() != o.m_operations.size())
        return false;

    unsigned s = m_operations.size();
    for (unsigned i = 0; i < s; i++) {
        if (*m_operations[i] != *o.m_operations[i])
            return false;
    }

    return true;
}

bool TransformOperations::operationsMatch(const TransformOperations& other) const
{
    size_t numOperations = operations().size();
    // If the sizes of the function lists don't match, the lists don't match
    if (numOperations != other.operations().size())
        return false;

    // If the types of each function are not the same, the lists don't match
    for (size_t i = 0; i < numOperations; ++i) {
        if (!operations()[i]->isSameType(*other.operations()[i]))
            return false;
    }
    return true;
}

TransformOperations TransformOperations::blendByMatchingOperations(const TransformOperations& from, const double& progress) const
{
    TransformOperations result;

    unsigned fromSize = from.operations().size();
    unsigned toSize = operations().size();
    unsigned size = std::max(fromSize, toSize);
    for (unsigned i = 0; i < size; i++) {
        RefPtr<TransformOperation> fromOperation = (i < fromSize) ? from.operations()[i].get() : 0;
        RefPtr<TransformOperation> toOperation = (i < toSize) ? operations()[i].get() : 0;
        RefPtr<TransformOperation> blendedOperation = toOperation ? toOperation->blend(fromOperation.get(), progress) : (fromOperation ? fromOperation->blend(0, progress, true) : nullptr);
        if (blendedOperation)
            result.operations().append(blendedOperation);
        else {
            RefPtr<TransformOperation> identityOperation = IdentityTransformOperation::create();
            if (progress > 0.5)
                result.operations().append(toOperation ? toOperation : identityOperation);
            else
                result.operations().append(fromOperation ? fromOperation : identityOperation);
        }
    }

    return result;
}

TransformOperations TransformOperations::blendByUsingMatrixInterpolation(const TransformOperations& from, double progress) const
{
    TransformOperations result;
    result.operations().append(InterpolatedTransformOperation::create(from, *this, progress));
    return result;
}

TransformOperations TransformOperations::blend(const TransformOperations& from, double progress) const
{
    if (from == *this || (!from.size() && !size()))
        return *this;

    // If either list is empty, use blendByMatchingOperations which has special logic for this case.
    if (!from.size() || !size() || from.operationsMatch(*this))
        return blendByMatchingOperations(from, progress);

    return blendByUsingMatrixInterpolation(from, progress);
}

static void findCandidatesInPlane(double px, double py, double nz, double* candidates, int* numCandidates)
{
    // The angle that this point is rotated with respect to the plane nz
    double phi = atan2(px, py);

    *numCandidates = 4;
    candidates[0] = phi; // The element at 0deg (maximum x)

    for (int i = 1; i < *numCandidates; ++i)
        candidates[i] = candidates[i - 1] + M_PI_2; // every 90 deg
    if (nz < 0.f) {
        for (int i = 0; i < *numCandidates; ++i)
            candidates[i] *= -1;
    }
}

// This method returns the bounding box that contains the starting point,
// the ending point, and any of the extrema (in each dimension) found across
// the circle described by the arc. These are then filtered to points that
// actually reside on the arc.
static void boundingBoxForArc(const FloatPoint3D& point, const RotateTransformOperation& fromTransform, const RotateTransformOperation& toTransform, double minProgress, double maxProgress, FloatBox& box)
{
    double candidates[6];
    int numCandidates = 0;

    FloatPoint3D axis(fromTransform.axis());
    double fromDegrees = fromTransform.angle();
    double toDegrees = toTransform.angle();

    if (axis.dot(toTransform.axis()) < 0)
        toDegrees *= -1;

    fromDegrees  = blend(fromDegrees, toTransform.angle(), minProgress);
    toDegrees = blend(toDegrees, fromTransform.angle(), 1.0 - maxProgress);
    if (fromDegrees > toDegrees)
        std::swap(fromDegrees, toDegrees);

    TransformationMatrix fromMatrix;
    TransformationMatrix toMatrix;
    fromMatrix.rotate3d(fromTransform.x(), fromTransform.y(), fromTransform.z(), fromDegrees);
    toMatrix.rotate3d(fromTransform.x(), fromTransform.y(), fromTransform.z(), toDegrees);

    FloatPoint3D fromPoint = fromMatrix.mapPoint(point);
    FloatPoint3D toPoint = toMatrix.mapPoint(point);

    if (box.isEmpty())
        box.setOrigin(fromPoint);
    else
        box.expandTo(fromPoint);

    box.expandTo(toPoint);

    switch (fromTransform.type()) {
    case TransformOperation::RotateX:
        findCandidatesInPlane(point.y(), point.z(), fromTransform.x(), candidates, &numCandidates);
        break;
    case TransformOperation::RotateY:
        findCandidatesInPlane(point.z(), point.x(), fromTransform.y(), candidates, &numCandidates);
        break;
    case TransformOperation::RotateZ:
        findCandidatesInPlane(point.x(), point.y(), fromTransform.z(), candidates, &numCandidates);
        break;
    default:
        {
            FloatPoint3D normal = axis;
            if (normal.isZero())
                return;
            normal.normalize();
            FloatPoint3D origin;
            FloatPoint3D toPoint = point - origin;
            FloatPoint3D center = origin + normal * toPoint.dot(normal);
            FloatPoint3D v1 = point - center;
            if (v1.isZero())
                return;

            v1.normalize();
            FloatPoint3D v2 = normal.cross(v1);
            // v1 is the basis vector in the direction of the point.
            // i.e. with a rotation of 0, v1 is our +x vector.
            // v2 is a perpenticular basis vector of our plane (+y).

            // Take the parametric equation of a circle.
            // (x = r*cos(t); y = r*sin(t);
            // We can treat that as a circle on the plane v1xv2
            // From that we get the parametric equations for a circle on the
            // plane in 3d space of
            // x(t) = r*cos(t)*v1.x + r*sin(t)*v2.x + cx
            // y(t) = r*cos(t)*v1.y + r*sin(t)*v2.y + cy
            // z(t) = r*cos(t)*v1.z + r*sin(t)*v2.z + cz
            // taking the derivative of (x, y, z) and solving for 0 gives us our
            // maximum/minimum x, y, z values
            // x'(t) = r*cos(t)*v2.x - r*sin(t)*v1.x = 0
            // tan(t) = v2.x/v1.x
            // t = atan2(v2.x, v1.x) + n*M_PI;

            candidates[0] = atan2(v2.x(), v1.x());
            candidates[1] = candidates[0] + M_PI;
            candidates[2] = atan2(v2.y(), v1.y());
            candidates[3] = candidates[2] + M_PI;
            candidates[4] = atan2(v2.z(), v1.z());
            candidates[5] = candidates[4] + M_PI;
            numCandidates = 6;
        }
        break;
    }

    double minRadians = deg2rad(fromDegrees);
    double maxRadians = deg2rad(toDegrees);
    // Once we have the candidates, we now filter them down to ones that
    // actually live on the arc, rather than the entire circle.
    for (int i = 0; i < numCandidates; ++i) {
        double radians = candidates[i];

        while (radians < minRadians)
            radians += 2.0 * M_PI;
        while (radians > maxRadians)
            radians -= 2.0 * M_PI;
        if (radians < minRadians)
            continue;

        TransformationMatrix rotation;
        rotation.rotate3d(axis.x(), axis.y(), axis.z(), rad2deg(radians));
        box.expandTo(rotation.mapPoint(point));
    }
}

bool TransformOperations::blendedBoundsForBox(const FloatBox& box, const TransformOperations& from, const double& minProgress, const double& maxProgress, FloatBox* bounds) const
{

    int fromSize = from.operations().size();
    int toSize = operations().size();
    int size = std::max(fromSize, toSize);

    *bounds = box;
    for (int i = size - 1; i >= 0; i--) {
        RefPtr<TransformOperation> fromOperation = (i < fromSize) ? from.operations()[i] : nullptr;
        RefPtr<TransformOperation> toOperation = (i < toSize) ? operations()[i] : nullptr;
        if (fromOperation && fromOperation->type() == TransformOperation::None)
            fromOperation = nullptr;

        if (toOperation && toOperation->type() == TransformOperation::None)
            toOperation = nullptr;

        TransformOperation::OperationType interpolationType = toOperation ? toOperation->type() :
            fromOperation ? fromOperation->type() :
            TransformOperation::None;
        if (fromOperation && toOperation && !fromOperation->canBlendWith(*toOperation.get()))
            return false;

        switch (interpolationType) {
        case TransformOperation::Identity:
            bounds->expandTo(box);
            continue;
        case TransformOperation::Translate:
        case TransformOperation::TranslateX:
        case TransformOperation::TranslateY:
        case TransformOperation::TranslateZ:
        case TransformOperation::Translate3D:
        case TransformOperation::Scale:
        case TransformOperation::ScaleX:
        case TransformOperation::ScaleY:
        case TransformOperation::ScaleZ:
        case TransformOperation::Scale3D:
        case TransformOperation::Skew:
        case TransformOperation::SkewX:
        case TransformOperation::SkewY:
        case TransformOperation::Perspective:
            {
                RefPtr<TransformOperation> fromTransform;
                RefPtr<TransformOperation> toTransform;
                if (!toOperation) {
                    fromTransform = fromOperation->blend(toOperation.get(), 1-minProgress, false);
                    toTransform = fromOperation->blend(toOperation.get(), 1-maxProgress, false);
                } else {
                    fromTransform = toOperation->blend(fromOperation.get(), minProgress, false);
                    toTransform = toOperation->blend(fromOperation.get(), maxProgress, false);
                }
                if (!fromTransform || !toTransform)
                    continue;
                TransformationMatrix fromMatrix;
                TransformationMatrix toMatrix;
                fromTransform->apply(fromMatrix, FloatSize());
                toTransform->apply(toMatrix, FloatSize());
                FloatBox fromBox = *bounds;
                FloatBox toBox = *bounds;
                fromMatrix.transformBox(fromBox);
                toMatrix.transformBox(toBox);
                *bounds = fromBox;
                bounds->expandTo(toBox);
                continue;
            }
        case TransformOperation::Rotate: // This is also RotateZ
        case TransformOperation::Rotate3D:
        case TransformOperation::RotateX:
        case TransformOperation::RotateY:
            {
                RefPtr<RotateTransformOperation> identityRotation;
                const RotateTransformOperation* fromRotation = nullptr;
                const RotateTransformOperation* toRotation = nullptr;
                if (fromOperation) {
                    fromRotation = static_cast<const RotateTransformOperation*>(fromOperation.get());
                    if (fromRotation->axis().isZero())
                        fromRotation = nullptr;
                }

                if (toOperation) {
                    toRotation = static_cast<const RotateTransformOperation*>(toOperation.get());
                    if (toRotation->axis().isZero())
                        toRotation = nullptr;
                }

                double fromAngle;
                double toAngle;
                FloatPoint3D axis;
                if (!RotateTransformOperation::shareSameAxis(fromRotation, toRotation, &axis, &fromAngle, &toAngle)) {
                    return(false);
                }

                if (!fromRotation) {
                    identityRotation = RotateTransformOperation::create(axis.x(), axis.y(), axis.z(), 0, fromOperation ? fromOperation->type() : toOperation->type());
                    fromRotation = identityRotation.get();
                }

                if (!toRotation) {
                    if (!identityRotation)
                        identityRotation = RotateTransformOperation::create(axis.x(), axis.y(), axis.z(), 0, fromOperation ? fromOperation->type() : toOperation->type());
                    toRotation = identityRotation.get();
                }

                FloatBox fromBox = *bounds;
                bool first = true;
                for (size_t i = 0; i < 2; ++i) {
                    for (size_t j = 0; j < 2; ++j) {
                        for (size_t k = 0; k < 2; ++k) {
                            FloatBox boundsForArc;
                            FloatPoint3D corner(fromBox.x(), fromBox.y(), fromBox.z());
                            corner += FloatPoint3D(i * fromBox.width(), j * fromBox.height(), k * fromBox.depth());
                            boundingBoxForArc(corner, *fromRotation, *toRotation, minProgress, maxProgress, boundsForArc);
                            if (first) {
                                *bounds = boundsForArc;
                                first = false;
                            } else {
                                bounds->expandTo(boundsForArc);
                            }
                        }
                    }
                }
            }
            continue;
        case TransformOperation::None:
            continue;
        case TransformOperation::Matrix:
        case TransformOperation::Matrix3D:
        case TransformOperation::Interpolated:
            return(false);
        }
    }

    return true;
}

TransformOperations TransformOperations::add(const TransformOperations& addend) const
{
    TransformOperations result;
    result.m_operations = operations();
    result.m_operations.appendVector(addend.operations());
    return result;
}

} // namespace blink
