/****************************************************************************
**
** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
** Contact: http://www.qt-project.org/legal
**
** 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 "animationclip_p.h"
#include <Qt3DAnimation/qanimationclip.h>
#include <Qt3DAnimation/qanimationcliploader.h>
#include <Qt3DAnimation/private/qanimationclip_p.h>
#include <Qt3DAnimation/private/qanimationcliploader_p.h>
#include <Qt3DAnimation/private/animationlogging_p.h>
#include <Qt3DAnimation/private/managers_p.h>
#include <Qt3DAnimation/private/gltfimporter_p.h>
#include <Qt3DRender/private/qurlhelper_p.h>

#include <QtCore/qbytearray.h>
#include <QtCore/qfile.h>
#include <QtCore/qjsonarray.h>
#include <QtCore/qjsondocument.h>
#include <QtCore/qjsonobject.h>
#include <QtCore/qurlquery.h>

QT_BEGIN_NAMESPACE

#define ANIMATION_INDEX_KEY     QLatin1String("animationIndex")
#define ANIMATION_NAME_KEY      QLatin1String("animationName")

namespace Qt3DAnimation {
namespace Animation {

AnimationClip::AnimationClip()
    : BackendNode(ReadWrite)
    , m_source()
    , m_status(QAnimationClipLoader::NotReady)
    , m_clipData()
    , m_dataType(Unknown)
    , m_name()
    , m_channels()
    , m_duration(0.0f)
    , m_channelComponentCount(0)
{
}

void AnimationClip::cleanup()
{
    setEnabled(false);
    m_handler = nullptr;
    m_source.clear();
    m_clipData.clearChannels();
    m_status = QAnimationClipLoader::NotReady;
    m_dataType = Unknown;
    m_channels.clear();
    m_duration = 0.0f;
    m_channelComponentCount = 0;

    clearData();
}

void AnimationClip::setStatus(QAnimationClipLoader::Status status)
{
    if (status != m_status) {
        m_status = status;
    }
}

void AnimationClip::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
    BackendNode::syncFromFrontEnd(frontEnd, firstTime);
    const QAbstractAnimationClip *node = qobject_cast<const QAbstractAnimationClip *>(frontEnd);
    if (!node)
        return;

    const QAnimationClip *clipNode = qobject_cast<const QAnimationClip *>(frontEnd);
    if (clipNode) {
        if (firstTime)
            m_dataType = Data;
        Q_ASSERT(m_dataType == Data);
        if (m_clipData != clipNode->clipData()) {
            m_clipData = clipNode->clipData();
            if (m_clipData.isValid())
                setDirty(Handler::AnimationClipDirty);
        }
    }

    const QAnimationClipLoader *loaderNode = qobject_cast<const QAnimationClipLoader *>(frontEnd);
    if (loaderNode) {
        if (firstTime)
            m_dataType = File;
        Q_ASSERT(m_dataType == File);
        if (m_source != loaderNode->source()) {
            m_source = loaderNode->source();
            if (!m_source.isEmpty())
                setDirty(Handler::AnimationClipDirty);
        }
    }
}

/*!
    \internal
    Called by LoadAnimationClipJob on the threadpool
 */
void AnimationClip::loadAnimation()
{
    qCDebug(Jobs) << Q_FUNC_INFO << m_source;
    clearData();

    // Load the data
    switch (m_dataType) {
    case File:
        loadAnimationFromUrl();
        break;

    case Data:
        loadAnimationFromData();
        break;

    default:
        Q_UNREACHABLE();
    }

    // Update the duration
    const float t = findDuration();
    setDuration(t);

    m_channelComponentCount = findChannelComponentCount();

    // If using a loader inform the frontend of the status change
    if (m_source.isEmpty()) {
        if (qFuzzyIsNull(t) || m_channelComponentCount == 0)
            setStatus(QAnimationClipLoader::Error);
        else
            setStatus(QAnimationClipLoader::Ready);
    }

    // notify all ClipAnimators and BlendedClipAnimators that depend on this clip,
    // that the clip has changed and that they are now dirty
    {
        QMutexLocker lock(&m_mutex);
        for (const Qt3DCore::QNodeId id : qAsConst(m_dependingAnimators)) {
            ClipAnimator *animator = m_handler->clipAnimatorManager()->lookupResource(id);
            if (animator)
                animator->animationClipMarkedDirty();
        }
        for (const Qt3DCore::QNodeId id : qAsConst(m_dependingBlendedAnimators)) {
            BlendedClipAnimator *animator = m_handler->blendedClipAnimatorManager()->lookupResource(id);
            if (animator)
                animator->animationClipMarkedDirty();
        }
        m_dependingAnimators.clear();
        m_dependingBlendedAnimators.clear();
    }

    qCDebug(Jobs) << "Loaded animation data:" << *this;
}

void AnimationClip::loadAnimationFromUrl()
{
    // TODO: Handle remote files
    QString filePath = Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(m_source);
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        qWarning() << "Could not find animation clip:" << filePath;
        setStatus(QAnimationClipLoader::Error);
        return;
    }

    // Extract the animationName or animationIndex from the url query parameters.
    // If both present, animationIndex wins.
    int animationIndex = -1;
    QString animationName;
    if (m_source.hasQuery()) {
        QUrlQuery query(m_source);
        if (query.hasQueryItem(ANIMATION_INDEX_KEY)) {
            bool ok = false;
            int i = query.queryItemValue(ANIMATION_INDEX_KEY).toInt(&ok);
            if (ok)
                animationIndex = i;
        }

        if (animationIndex == -1 && query.hasQueryItem(ANIMATION_NAME_KEY)) {
            animationName = query.queryItemValue(ANIMATION_NAME_KEY);
        }

        qCDebug(Jobs) << "animationIndex =" << animationIndex;
        qCDebug(Jobs) << "animationName =" << animationName;
    }

    // TODO: Convert to plugins
    // Load glTF or "native"
    if (filePath.endsWith(QLatin1String("gltf"))) {
        qCDebug(Jobs) << "Loading glTF animation from" << filePath;
        GLTFImporter gltf;
        gltf.load(&file);
        auto nameAndChannels = gltf.createAnimationData(animationIndex, animationName);
        m_name = nameAndChannels.name;
        m_channels = nameAndChannels.channels;
    } else if (filePath.endsWith(QLatin1String("json"))) {
        // Native format
        QByteArray animationData = file.readAll();
        QJsonDocument document = QJsonDocument::fromJson(animationData);
        QJsonObject rootObject = document.object();

        // TODO: Allow loading of a named animation from a file containing many
        const QJsonArray animationsArray = rootObject[QLatin1String("animations")].toArray();
        qCDebug(Jobs) << "Found" << animationsArray.size() << "animations:";
        for (int i = 0; i < animationsArray.size(); ++i) {
            QJsonObject animation = animationsArray.at(i).toObject();
            qCDebug(Jobs) << "Animation Name:" << animation[QLatin1String("animationName")].toString();
        }

        // Find which animation clip to load from the file.
        // Give priority to animationIndex over animationName
        if (animationIndex >= animationsArray.size()) {
            qCWarning(Jobs) << "Invalid animation index. Skipping.";
            return;
        }

        if (animationsArray.size() == 1) {
            animationIndex = 0;
        } else if (animationIndex < 0 && !animationName.isEmpty()) {
            // Can we find an animation of the correct name?
            bool foundAnimation = false;
            for (int i = 0; i < animationsArray.size(); ++i) {
                if (animationsArray.at(i)[ANIMATION_NAME_KEY].toString() == animationName) {
                    animationIndex = i;
                    foundAnimation = true;
                    break;
                }
            }

            if (!foundAnimation) {
                qCWarning(Jobs) << "Invalid animation name. Skipping.";
                return;
            }
        }

        if (animationIndex < 0 || animationIndex >= animationsArray.size()) {
            qCWarning(Jobs) << "Failed to find animation. Skipping.";
            return;
        }

        QJsonObject animation = animationsArray.at(animationIndex).toObject();
        m_name = animation[QLatin1String("animationName")].toString();

        QJsonArray channelsArray = animation[QLatin1String("channels")].toArray();
        const int channelCount = channelsArray.size();
        m_channels.resize(channelCount);
        for (int i = 0; i < channelCount; ++i) {
            const QJsonObject group = channelsArray.at(i).toObject();
            m_channels[i].read(group);
        }
    } else {
        qWarning() << "Unknown animation clip type. Please use json or glTF 2.0";
        setStatus(QAnimationClipLoader::Error);
    }
}

void AnimationClip::loadAnimationFromData()
{
    // Reformat data from QAnimationClipData to backend format
    m_channels.resize(m_clipData.channelCount());
    int i = 0;
    for (const auto &frontendChannel : qAsConst(m_clipData))
        m_channels[i++].setFromQChannel(frontendChannel);
}

void AnimationClip::addDependingClipAnimator(const Qt3DCore::QNodeId &id)
{
    QMutexLocker lock(&m_mutex);
    m_dependingAnimators.push_back(id);
}

void AnimationClip::addDependingBlendedClipAnimator(const Qt3DCore::QNodeId &id)
{
    QMutexLocker lock(&m_mutex);
    m_dependingBlendedAnimators.push_back(id);
}

void AnimationClip::setDuration(float duration)
{
    if (qFuzzyCompare(duration, m_duration))
        return;

    m_duration = duration;
}

int AnimationClip::channelIndex(const QString &channelName, int jointIndex) const
{
    const int channelCount = m_channels.size();
    for (int i = 0; i < channelCount; ++i) {
        if (m_channels[i].name == channelName
            && (jointIndex == -1 || m_channels[i].jointIndex == jointIndex)) {
            return i;
        }
    }
    return -1;
}

/*!
    \internal

    Given the index of a channel, \a channelIndex, calculates
    the base index of the first channelComponent in this group. For example, if
    there are two channel groups each with 3 channels and you request
    the channelBaseIndex(1), the return value will be 3. Indices 0-2 are
    for the first group, so the first channel of the second group occurs
    at index 3.
 */
int AnimationClip::channelComponentBaseIndex(int channelIndex) const
{
    int index = 0;
    for (int i = 0; i < channelIndex; ++i)
        index += m_channels[i].channelComponents.size();
    return index;
}

void AnimationClip::clearData()
{
    m_name.clear();
    m_channels.clear();
}

float AnimationClip::findDuration()
{
    // Iterate over the contained fcurves and find the longest one
    double tMax = 0.0;
    for (const Channel &channel : qAsConst(m_channels)) {
        for (const ChannelComponent &channelComponent : qAsConst(channel.channelComponents)) {
            const float t = channelComponent.fcurve.endTime();
            if (t > tMax)
                tMax = t;
        }
    }
    return tMax;
}

int AnimationClip::findChannelComponentCount()
{
    int channelCount = 0;
    for (const Channel &channel : qAsConst(m_channels))
        channelCount += channel.channelComponents.size();
    return channelCount;
}

} // namespace Animation
} // namespace Qt3DAnimation

QT_END_NAMESPACE
