/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Quick Designer Components.
**
** $QT_BEGIN_LICENSE:GPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qquickkeyframe_p.h"

#include "qquicktimeline_p.h"

#include <QtCore/qdebug.h>
#include <QtCore/QVariantAnimation>
#include <QtCore/qmath.h>
#include <QtGui/qpainter.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQml/QQmlProperty>

#include <private/qvariantanimation_p.h>

#include <algorithm>

QT_BEGIN_NAMESPACE

class QQuickKeyframeGroupPrivate : public QObjectPrivate
{
    Q_DECLARE_PUBLIC(QQuickKeyframeGroup)
public:
    QQuickKeyframeGroupPrivate() = default;

    QObject *target = nullptr;
    QString propertyName;
    bool componentComplete = false;
    int userType = -1;

protected:
    void setupKeyframes();

    static void append_keyframe(QQmlListProperty<QQuickKeyframe> *list, QQuickKeyframe *a);
    static int keyframe_count(QQmlListProperty<QQuickKeyframe> *list);
    static QQuickKeyframe* keyframe_at(QQmlListProperty<QQuickKeyframe> *list, int pos);
    static void clear_keyframes(QQmlListProperty<QQuickKeyframe> *list);

    QList<QQuickKeyframe *> keyframes;
    QList<QQuickKeyframe *> sortedKeyframes;

    QVariant originalValue;
};

void QQuickKeyframeGroupPrivate::setupKeyframes()
{
    sortedKeyframes = keyframes;
    std::sort(sortedKeyframes.begin(), sortedKeyframes.end(), [](const QQuickKeyframe *first, const QQuickKeyframe *second) {
        return first->frame() < second->frame();
    });
}

void QQuickKeyframeGroupPrivate::append_keyframe(QQmlListProperty<QQuickKeyframe> *list, QQuickKeyframe *a)
{
    auto q = static_cast<QQuickKeyframeGroup *>(list->object);
    q->d_func()->keyframes.append(a);
    q->d_func()->setupKeyframes();
    q->reset();
}

int QQuickKeyframeGroupPrivate::keyframe_count(QQmlListProperty<QQuickKeyframe> *list)
{
    auto q = static_cast<QQuickKeyframeGroup *>(list->object);
    return q->d_func()->keyframes.count();
}

QQuickKeyframe* QQuickKeyframeGroupPrivate::keyframe_at(QQmlListProperty<QQuickKeyframe> *list, int pos)
{
    auto q = static_cast<QQuickKeyframeGroup *>(list->object);
    return q->d_func()->keyframes.at(pos);
}

void QQuickKeyframeGroupPrivate::clear_keyframes(QQmlListProperty<QQuickKeyframe> *list)
{
    auto q = static_cast<QQuickKeyframeGroup *>(list->object);
    while (q->d_func()->keyframes.count()) {
        QQuickKeyframe *firstKeyframe = q->d_func()->keyframes.at(0);
        q->d_func()->keyframes.removeAll(firstKeyframe);
    }
}

class QQuickKeyframePrivate : public QObjectPrivate
{
    Q_DECLARE_PUBLIC(QQuickKeyframe)
public:
    QQuickKeyframePrivate() = default;

    qreal frame = 0;
    QEasingCurve easingCurve;
    QVariant value;
};

/*!
    \qmltype Keyframe
    \inherits QObject
    \instantiates QQuickKeyframe
    \inqmlmodule QtQuick.Timeline
    \ingroup qtqmltypes

    \brief A keyframe.

    The value of a keyframe on a timeline.

    An easing curve can be attached to the keyframe.
*/

/*!
    \qmlproperty double Keyframe::frame

    The position of the keyframe on the timeline.
*/

/*!
    \qmlproperty var Keyframe::easing

    The easing curve attached to the keyframe.
*/

/*!
    \qmlproperty var Keyframe::value

    The value of the keyframe.
*/

/*!
    \qmlsignal Keyframe::easingCurveChanged

    This signal is emitted when the easing curve attached to the keyframe
    changes.
*/

QQuickKeyframe::QQuickKeyframe(QObject *parent)
    : QObject(*(new QQuickKeyframePrivate), parent)
{
}

qreal QQuickKeyframe::frame() const
{
    Q_D(const QQuickKeyframe);
    return d->frame;
}

void QQuickKeyframe::setFrame(qreal f)
{
    Q_D(QQuickKeyframe);
    if (d->frame == f)
        return;
    d->frame = f;

    reset();

    emit frameChanged();
}

void QQuickKeyframe::reset()
{
    auto keyframes = qobject_cast<QQuickKeyframeGroup*>(parent());
    if (keyframes)
        keyframes->reset();
}

QQuickKeyframe::QQuickKeyframe(QQuickKeyframePrivate &dd, QObject *parent)
    : QObject(dd, parent)
{
}

/*!
    \qmltype KeyframeGroup
    \inherits QObject
    \instantiates QQuickKeyframeGroup
    \inqmlmodule QtQuick.Timeline
    \ingroup qtqmltypes

    \brief A keyframe group.

    A keyframe group contains all keyframes for a specific property of an item
    and always belongs to a timeline.
*/

/*!
    \qmlproperty var KeyframeGroup::target

    The item that is targeted by the keyframe group.
*/

/*!
    \qmlproperty string KeyframeGroup::property

    The property that is targeted by the keyframe group.
*/

/*!
    \qmlproperty list KeyframeGroup::keyframes
    \readonly

    A list of keyframes that belong to the keyframe group.
*/

QQuickKeyframeGroup::QQuickKeyframeGroup(QObject *parent)
    : QObject(*(new QQuickKeyframeGroupPrivate), parent)
{

}

QQmlListProperty<QQuickKeyframe> QQuickKeyframeGroup::keyframes()
{
    Q_D(QQuickKeyframeGroup);

    return { this, &d->keyframes, QQuickKeyframeGroupPrivate::append_keyframe,
                QQuickKeyframeGroupPrivate::keyframe_count,
                QQuickKeyframeGroupPrivate::keyframe_at,
                QQuickKeyframeGroupPrivate::clear_keyframes };
}

QObject *QQuickKeyframeGroup::target() const
{
    Q_D(const QQuickKeyframeGroup);
    return d->target;
}

void QQuickKeyframeGroup::setTargetObject(QObject *o)
{
    Q_D(QQuickKeyframeGroup);
    if (d->target == o)
        return;
    d->target = o;

    if (!property().isEmpty())
        init();

    emit targetChanged();
}

QString QQuickKeyframeGroup::property() const
{
    Q_D(const QQuickKeyframeGroup);
    return d->propertyName;
}

void QQuickKeyframeGroup::setProperty(const QString &n)
{
    Q_D(QQuickKeyframeGroup);
    if (d->propertyName == n)
        return;
    d->propertyName = n;

    if (target())
        init();

    emit propertyChanged();
}

QVariant QQuickKeyframeGroup::evaluate(qreal frame) const
{
    Q_D(const QQuickKeyframeGroup);

    if (d->sortedKeyframes.isEmpty())
        return QVariant();

    static QQuickKeyframe dummy;
    auto timeline = qobject_cast<QQuickTimeline*>(parent());
    if (timeline)
        dummy.setFrame(timeline->startFrame() - 0.0001);
    dummy.setValue(d->originalValue);

     QQuickKeyframe *lastFrame = &dummy;

    for (auto keyFrame :  qAsConst(d->sortedKeyframes)) {
        if (qFuzzyCompare(frame, keyFrame->frame()) || frame < keyFrame->frame())
            return keyFrame->evaluate(lastFrame, frame, d->userType);
        lastFrame = keyFrame;
    }

    return lastFrame->value();
}

void QQuickKeyframeGroup::setProperty(qreal frame)
{
    if (target()) {
        QQmlProperty qmlProperty(target(), property());

        if (!qmlProperty.write(evaluate(frame)))
            qWarning() << "Cannot set property" << property();
    }
}

void QQuickKeyframeGroup::init()
{
    Q_D(QQuickKeyframeGroup);
    if (target()) {
        d->originalValue = QQmlProperty::read(target(), property());
        d->userType = QQmlProperty(target(), property()).property().userType();
        if (property().contains(QLatin1Char('.'))) {
            if (d->userType == QMetaType::QVector2D
                    || d->userType == QMetaType::QVector3D
                    || d->userType == QMetaType::QVector4D
                    || d->userType == QMetaType::QQuaternion)
                d->userType = QMetaType::Double;
        }
    }
}

void QQuickKeyframeGroup::resetDefaultValue()
{
    Q_D(QQuickKeyframeGroup);
    QQmlProperty::write(target(), property(), d->originalValue);
}

void QQuickKeyframeGroup::reset()
{
    Q_D(QQuickKeyframeGroup);
    if (!d->componentComplete)
        return;

    auto *timeline = qobject_cast<QQuickTimeline*>(parent());
    if (timeline)
        timeline->reevaulate();
}

void QQuickKeyframeGroup::setupKeyframes()
{
    Q_D(QQuickKeyframeGroup);

    if (d->componentComplete)
        d->setupKeyframes();
}

void QQuickKeyframeGroup::classBegin()
{
    Q_D(QQuickKeyframeGroup);
    d->componentComplete = false;
}

void QQuickKeyframeGroup::componentComplete()
{
    Q_D(QQuickKeyframeGroup);
    d->componentComplete = true;
    setupKeyframes();
}

QEasingCurve QQuickKeyframe::easing() const
{
    Q_D(const QQuickKeyframe);
    return d->easingCurve;
}

void QQuickKeyframe::setEasing(const QEasingCurve &e)
{
    Q_D(QQuickKeyframe);
    if (d->easingCurve == e)
        return;

    d->easingCurve = e;

    reset();

    emit easingCurveChanged();
}

QVariant QQuickKeyframe::value() const
{
    Q_D(const QQuickKeyframe);
    return d->value;
}

void QQuickKeyframe::setValue(const QVariant &v)
{
    Q_D(QQuickKeyframe);
    if (d->value == v)
        return;
    d->value = v;

    reset();

    emit valueChanged();
}

QVariant QQuickKeyframe::evaluate(QQuickKeyframe *pre, qreal frametime, int userType) const
{
    QVariantAnimation::Interpolator interpolator = QVariantAnimationPrivate::getInterpolator(userType);
    if (!pre)
        return value();

    QVariant preValue = pre->value();
    qreal preFrame = pre->frame();

    qreal duration = frame() - preFrame;
    qreal offset = frametime - preFrame;

    qreal progress = easing().valueForProgress(offset / duration);

    preValue.convert(userType);
    QVariant convertedValue = value();
    convertedValue.convert(userType);

    if (!interpolator) {
        if (progress < 1.0)
            return preValue;

        return convertedValue;
    }

    if (preValue.isValid() && convertedValue.isValid())
        return interpolator(preValue.constData(), convertedValue.constData(), progress);

    qWarning() << "invalid keyframe target" << preValue << convertedValue << userType;

    return QVariant();
}

QT_END_NAMESPACE


