/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or later as published by the Free
** Software Foundation and appearing in the file LICENSE.GPL included in
** the packaging of this file. Please review the following information to
** ensure the GNU General Public License version 2.0 requirements will be
** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qkeyframeanimation.h"
#include "Qt3DAnimation/private/qkeyframeanimation_p.h"

#include <cmath>

QT_BEGIN_NAMESPACE

namespace Qt3DAnimation {

/*!
    \class Qt3DAnimation::QKeyframeAnimation
    \brief A class implementing simple keyframe animation to a QTransform.
    \inmodule Qt3DAnimation
    \since 5.9
    \inherits Qt3DAnimation::QAbstractAnimation

    A Qt3DAnimation::QKeyframeAnimation class implements simple keyframe animation
    that can be used to animate \l QTransform. The keyframes consists of multiple
    timed QTransforms, which are interpolated and applied to the target \l QTransform.
    \l QEasingCurve is used between keyframes to control the interpolator. RepeatMode
    can be set for when the position set to the QKeyframeAnimation is below or above
    the values defined in the keyframe positions.
*/

/*!
    \qmltype KeyframeAnimation
    \brief A type implementing simple keyframe animation to a Transform.
    \inqmlmodule Qt3D.Animation
    \since 5.9
    \inherits AbstractAnimation
    \instantiates Qt3DAnimation::QKeyframeAnimation

    A KeyframeAnimation type implements simple keyframe animation
    that can be used to animate \l Transform. The keyframes consists of multiple
    timed \l {Qt3D.Core::Transform}s, which are interpolated and applied
    to the target Transform. EasingCurve is used between keyframes to control
    the interpolator. RepeatMode can be set for when the position set to the
    KeyframeAnimation is less or or greater than the values defined in the keyframe positions.
*/

/*!
    \property Qt3DAnimation::QKeyframeAnimation::framePositions
    Holds the positions of the keyframes. Each position in the list specifies the position
    of the corresponding keyframe with the same index. The values must be in an ascending order.
    Values can be positive or negative and do not have any predefined unit.
*/
/*!
    \property Qt3DAnimation::QKeyframeAnimation::target
    Holds the target QTransform the animation is applied to.
*/
/*!
    \property Qt3DAnimation::QKeyframeAnimation::easing
    Holds the easing curve of the interpolator between keyframes.
*/
/*!
    \property Qt3DAnimation::QKeyframeAnimation::targetName
    Holds the name of the target transform. This is a convenience property making it
    easier to match the target transform to the keyframe animation. The name
    is usually same as the name of the parent entity of the target transform, but
    does not have to be.
*/
/*!
    \property Qt3DAnimation::QKeyframeAnimation::startMode
    Holds the repeat mode for the position values less than the first frame position.
*/
/*!
    \property Qt3DAnimation::QKeyframeAnimation::endMode
    Holds the repeat mode for the position values greater than the last frame position.
*/
/*!
    \enum QKeyframeAnimation::RepeatMode

    This enumeration specifies how position values outside keyframe values are handled.
    \value None The animation is not applied to the target transform.
    \value Constant The edge keyframe value is used.
    \value Repeat The animation is repeated.
*/
/*!
    \qmlproperty list<real> KeyframeAnimation::framePositions
    Holds the positions of the keyframes. Each position in the list specifies the position
    of the corresponding keyframe. The values must be in an ascending order. Values can
    be positive or negative and do not have any predefined unit.
*/
/*!
    \qmlproperty Transform KeyframeAnimation::target
    Holds the target Transform the animation is applied to.
*/
/*!
    \qmlproperty EasingCurve KeyframeAnimation::easing
    Holds the easing curve of the interpolator between keyframes.
*/
/*!
    \qmlproperty string KeyframeAnimation::targetName
    Holds the name of the target transform. This is a convenience property making it
    easier to match the target transform to the keyframe animation. The name
    is usually same as the name of the parent entity of the target transform, but
    does not have to be.
*/
/*!
    \qmlproperty enumeration KeyframeAnimation::startMode
    Holds the repeat mode for the position values less than the first frame position.
    \list
    \li None
    \li Constant
    \li Repeat
    \endlist
*/
/*!
    \qmlproperty enumeration KeyframeAnimation::endMode
    Holds the repeat mode for the position values greater than the last frame position.
    \list
    \li None
    \li Constant
    \li Repeat
    \endlist
*/
/*!
    \qmlproperty list<Transform> KeyframeAnimation::keyframes
    Holds the list of keyframes in the keyframe animation.
*/

QKeyframeAnimationPrivate::QKeyframeAnimationPrivate()
    : QAbstractAnimationPrivate(QAbstractAnimation::KeyframeAnimation)
    , m_target(nullptr)
    , m_minposition(0.0f)
    , m_maxposition(0.0f)
    , m_startMode(QKeyframeAnimation::Constant)
    , m_endMode(QKeyframeAnimation::Constant)
{

}

/*!
    Constructs an QKeyframeAnimation with \a parent.
*/
QKeyframeAnimation::QKeyframeAnimation(QObject *parent)
    : QAbstractAnimation(*new QKeyframeAnimationPrivate(), parent)
{
    Q_D(QKeyframeAnimation);
    d->m_positionConnection = QObject::connect(this, &QAbstractAnimation::positionChanged,
                                               this, &QKeyframeAnimation::updateAnimation);
}


void QKeyframeAnimation::setFramePositions(const QVector<float> &positions)
{
    Q_D(QKeyframeAnimation);
    d->m_framePositions = positions;
    d->m_position = -1.0f;
    if (d->m_framePositions.size() == 0) {
        d->m_minposition = d->m_maxposition = 0.0f;
        return;
    }
    d->m_minposition = d->m_framePositions.first();
    d->m_maxposition = d->m_framePositions.last();
    float lastPos = d->m_minposition;
    for (float p : qAsConst(d->m_framePositions)) {
        if (p < lastPos || p > d->m_maxposition)
            qWarning() << "positions not ordered correctly";
        lastPos = p;
    }
    setDuration(d->m_maxposition);
}

/*!
    Sets the \a keyframes of the animation. Old keyframes are cleared.
 */
void QKeyframeAnimation::setKeyframes(const QVector<Qt3DCore::QTransform *> &keyframes)
{
    Q_D(QKeyframeAnimation);
    d->m_keyframes = keyframes;
}

// slerp which allows long path
QQuaternion lslerp(QQuaternion q1, QQuaternion q2, float t)
{
    QQuaternion ret;
    // Handle the easy cases first.
    if (t <= 0.0f)
        return q1;
    else if (t >= 1.0f)
        return q2;

    float cos = qBound(-1.0f, QQuaternion::dotProduct(q1, q2), 1.0f);
    float angle = std::acos(cos);
    float sin = std::sin(angle);
    if (!qFuzzyIsNull(sin)) {
        float a = std::sin((1.0 - t) * angle) / sin;
        float b = std::sin(t * angle) / sin;
        ret = (q1 * a + q2 * b).normalized();
    } else {
        ret = q1 * (1.0f-t) + q2 * t;
    }
    return ret;
}

void QKeyframeAnimationPrivate::calculateFrame(float position)
{
    if (m_target && m_framePositions.size() > 0
        && m_keyframes.size() == m_framePositions.size()) {
        if (position < m_minposition) {
            if (m_startMode == QKeyframeAnimation::None) {
                return;
            } else if (m_startMode == QKeyframeAnimation::Constant) {
                m_target->setRotation(m_keyframes.first()->rotation());
                m_target->setScale3D(m_keyframes.first()->scale3D());
                m_target->setTranslation(m_keyframes.first()->translation());
                return;
            } else {
                // must be repeat
                position = std::fmod(-(position - m_minposition), m_maxposition - m_minposition)
                                     + m_minposition;
            }
        } else if (position >= m_maxposition) {
            if (m_endMode == QKeyframeAnimation::None) {
                return;
            } else if (m_endMode == QKeyframeAnimation::Constant) {
                m_target->setRotation(m_keyframes.last()->rotation());
                m_target->setScale3D(m_keyframes.last()->scale3D());
                m_target->setTranslation(m_keyframes.last()->translation());
                return;
            } else {
                // must be repeat
                position = std::fmod(position - m_minposition, m_maxposition - m_minposition)
                                     + m_minposition;
            }
        }
        if (position >= m_minposition && position < m_maxposition) {
            for (int i = 0; i < m_framePositions.size() - 1; i++) {
                if (position >= m_framePositions.at(i)
                    && position < m_framePositions.at(i+1)) {
                    float ip = (position - m_framePositions.at(i))
                                / (m_framePositions.at(i+1) - m_framePositions.at(i));
                    float eIp = m_easing.valueForProgress(ip);
                    float eIip = 1.0f - eIp;

                    Qt3DCore::QTransform *a = m_keyframes.at(i);
                    Qt3DCore::QTransform *b = m_keyframes.at(i+1);

                    QVector3D s = a->scale3D() * eIip + b->scale3D() * eIp;
                    QVector3D t = a->translation() * eIip + b->translation() * eIp;
                    QQuaternion r = QQuaternion::slerp(a->rotation(), b->rotation(), eIp);

                    m_target->setRotation(r);
                    m_target->setScale3D(s);
                    m_target->setTranslation(t);
                    return;
                }
            }
        }
    }
}

void QKeyframeAnimation::updateAnimation(float position)
{
    Q_D(QKeyframeAnimation);
    d->calculateFrame(position);
}

QVector<float> QKeyframeAnimation::framePositions() const
{
    Q_D(const QKeyframeAnimation);
    return d->m_framePositions;
}

/*!
    Returns the list of keyframes.
 */
QVector<Qt3DCore::QTransform *> QKeyframeAnimation::keyframeList() const
{
    Q_D(const QKeyframeAnimation);
    return d->m_keyframes;
}

void QKeyframeAnimation::setTarget(Qt3DCore::QTransform *target)
{
    Q_D(QKeyframeAnimation);
    if (d->m_target != target) {
        d->m_target = target;
        emit targetChanged(d->m_target);
        d->m_position = -1.0f;

        if (target) {
            d->m_baseScale = target->scale3D();
            d->m_baseTranslation = target->translation();
            d->m_baseRotation = target->rotation();
        }
    }
}

QKeyframeAnimation::RepeatMode QKeyframeAnimation::startMode() const
{
    Q_D(const QKeyframeAnimation);
    return d->m_startMode;
}

QKeyframeAnimation::RepeatMode QKeyframeAnimation::endMode() const
{
    Q_D(const QKeyframeAnimation);
    return d->m_endMode;
}

void QKeyframeAnimation::setEasing(const QEasingCurve &easing)
{
    Q_D(QKeyframeAnimation);
    if (d->m_easing != easing) {
        d->m_easing = easing;
        emit easingChanged(easing);
    }
}

void QKeyframeAnimation::setTargetName(const QString &name)
{
    Q_D(QKeyframeAnimation);
    if (d->m_targetName != name) {
        d->m_targetName = name;
        emit targetNameChanged(name);
    }
}

void QKeyframeAnimation::setStartMode(QKeyframeAnimation::RepeatMode mode)
{
    Q_D(QKeyframeAnimation);
    if (d->m_startMode != mode) {
        d->m_startMode = mode;
        emit startModeChanged(mode);
    }
}

void QKeyframeAnimation::setEndMode(QKeyframeAnimation::RepeatMode mode)
{
    Q_D(QKeyframeAnimation);
    if (mode != d->m_endMode) {
        d->m_endMode = mode;
        emit endModeChanged(mode);
    }
}

/*!
    Adds new \a keyframe at the end of the animation. The QTransform can
    be added to the animation multiple times.
 */
void QKeyframeAnimation::addKeyframe(Qt3DCore::QTransform *keyframe)
{
    Q_D(QKeyframeAnimation);
    d->m_keyframes.push_back(keyframe);
}

/*!
    Removes a \a keyframe from the animation. If the same QTransform
    is set as keyframe multiple times, all occurrences are removed.
 */
void QKeyframeAnimation::removeKeyframe(Qt3DCore::QTransform *keyframe)
{
    Q_D(QKeyframeAnimation);
    d->m_keyframes.removeAll(keyframe);
}

QString QKeyframeAnimation::targetName() const
{
    Q_D(const QKeyframeAnimation);
    return d->m_targetName;
}

QEasingCurve QKeyframeAnimation::easing() const
{
    Q_D(const QKeyframeAnimation);
    return d->m_easing;
}

Qt3DCore::QTransform *QKeyframeAnimation::target() const
{
    Q_D(const QKeyframeAnimation);
    return d->m_target;
}

} // Qt3DAnimation

QT_END_NAMESPACE
