/*
 * 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/config.h"
#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
