/****************************************************************************
**
** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 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.LGPL3 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-3.0.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 (at your option) the GNU General
** Public license version 3 or 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.GPL2 and 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-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "gltfgeometryloader.h"

#include <QtCore/QDir>
#include <QtCore/QJsonArray>
#include <QtCore/QJsonObject>
#include <QtCore/QVersionNumber>

#include <QtGui/QOpenGLTexture>

#include <Qt3DRender/QGeometry>
#include <Qt3DRender/private/renderlogging_p.h>

QT_BEGIN_NAMESPACE

#ifndef qUtf16PrintableImpl // -Impl is a Qt 5.8 feature
#  define qUtf16PrintableImpl(string) \
    static_cast<const wchar_t*>(static_cast<const void*>(string.utf16()))
#endif

namespace Qt3DRender {

Q_LOGGING_CATEGORY(GLTFGeometryLoaderLog, "Qt3D.GLTFGeometryLoader", QtWarningMsg)

#define KEY_ASSET        QLatin1String("asset")
#define KEY_ACCESSORS    QLatin1String("accessors")
#define KEY_ATTRIBUTES   QLatin1String("attributes")
#define KEY_BUFFER       QLatin1String("buffer")
#define KEY_BUFFERS      QLatin1String("buffers")
#define KEY_BYTE_LENGTH  QLatin1String("byteLength")
#define KEY_BYTE_OFFSET  QLatin1String("byteOffset")
#define KEY_BYTE_STRIDE  QLatin1String("byteStride")
#define KEY_COUNT        QLatin1String("count")
#define KEY_INDICES      QLatin1String("indices")
#define KEY_MATERIAL     QLatin1String("material")
#define KEY_MESHES       QLatin1String("meshes")
#define KEY_NAME         QLatin1String("name")
#define KEY_PRIMITIVES   QLatin1String("primitives")
#define KEY_TARGET       QLatin1String("target")
#define KEY_TYPE         QLatin1String("type")
#define KEY_URI          QLatin1String("uri")
#define KEY_VERSION      QLatin1String("version")

#define KEY_BUFFER_VIEW         QLatin1String("bufferView")
#define KEY_BUFFER_VIEWS        QLatin1String("bufferViews")
#define KEY_COMPONENT_TYPE      QLatin1String("componentType")

GLTFGeometryLoader::GLTFGeometryLoader()
    : m_geometry(nullptr)
{
}

GLTFGeometryLoader::~GLTFGeometryLoader()
{
    cleanup();
}

QGeometry *GLTFGeometryLoader::geometry() const
{
    return m_geometry;
}

bool GLTFGeometryLoader::load(QIODevice *ioDev, const QString &subMesh)
{
    Q_UNUSED(subMesh);

    QByteArray jsonData = ioDev->readAll();
    QJsonDocument sceneDocument = QJsonDocument::fromBinaryData(jsonData);
    if (sceneDocument.isNull())
        sceneDocument = QJsonDocument::fromJson(jsonData);

    if (Q_UNLIKELY(!setJSON(sceneDocument))) {
        qCWarning(GLTFGeometryLoaderLog, "not a JSON document");
        return false;
    }

    auto file = qobject_cast<QFile*>(ioDev);
    if (file) {
        QFileInfo finfo(file->fileName());
        setBasePath(finfo.dir().absolutePath());
    }

    m_mesh = subMesh;

    parse();

    return true;
}

GLTFGeometryLoader::BufferData::BufferData()
    : length(0)
    , data(nullptr)
{
}

GLTFGeometryLoader::BufferData::BufferData(const QJsonObject &json)
    : length(json.value(KEY_BYTE_LENGTH).toInt())
    , path(json.value(KEY_URI).toString())
    , data(nullptr)
{
}

GLTFGeometryLoader::AccessorData::AccessorData()
    : bufferViewIndex(0)
    , type(QAttribute::Float)
    , dataSize(0)
    , count(0)
    , offset(0)
    , stride(0)
{

}

GLTFGeometryLoader::AccessorData::AccessorData(const QJsonObject &json)
    : bufferViewName(json.value(KEY_BUFFER_VIEW).toString())
    , bufferViewIndex(json.value(KEY_BUFFER_VIEW).toInt(-1))
    , type(accessorTypeFromJSON(json.value(KEY_COMPONENT_TYPE).toInt()))
    , dataSize(accessorDataSizeFromJson(json.value(KEY_TYPE).toString()))
    , count(json.value(KEY_COUNT).toInt())
    , offset(0)
    , stride(0)
{
    const auto byteOffset = json.value(KEY_BYTE_OFFSET);
    if (!byteOffset.isUndefined())
        offset = byteOffset.toInt();
    const auto byteStride = json.value(KEY_BYTE_STRIDE);
    if (!byteStride.isUndefined())
        stride = byteStride.toInt();
}

void GLTFGeometryLoader::setBasePath(const QString &path)
{
    m_basePath = path;
}

bool GLTFGeometryLoader::setJSON(const QJsonDocument &json )
{
    if (!json.isObject())
        return false;

    m_json = json;

    cleanup();

    return true;
}

QString GLTFGeometryLoader::standardAttributeNameFromSemantic(const QString &semantic)
{
    //Standard Attributes
    if (semantic.startsWith(QLatin1String("POSITION")))
        return QAttribute::defaultPositionAttributeName();
    if (semantic.startsWith(QLatin1String("NORMAL")))
        return QAttribute::defaultNormalAttributeName();
    if (semantic.startsWith(QLatin1String("TEXCOORD")))
        return QAttribute::defaultTextureCoordinateAttributeName();
    if (semantic.startsWith(QLatin1String("COLOR")))
        return QAttribute::defaultColorAttributeName();
    if (semantic.startsWith(QLatin1String("TANGENT")))
        return QAttribute::defaultTangentAttributeName();
    if (semantic.startsWith(QLatin1String("JOINTS")))
        return QAttribute::defaultJointIndicesAttributeName();
    if (semantic.startsWith(QLatin1String("WEIGHTS")))
        return QAttribute::defaultJointWeightsAttributeName();

    return QString();
}

void GLTFGeometryLoader::parse()
{
    // Find the glTF version
    const QJsonObject asset = m_json.object().value(KEY_ASSET).toObject();
    const QString versionString = asset.value(KEY_VERSION).toString();
    const auto version = QVersionNumber::fromString(versionString);
    switch (version.majorVersion()) {
    case 1:
        parseGLTF1();
        break;

    case 2:
        parseGLTF2();
        break;

    default:
        qWarning() << "Unsupported version of glTF" << versionString;
    }
}

void GLTFGeometryLoader::parseGLTF1()
{
    const QJsonObject buffers = m_json.object().value(KEY_BUFFERS).toObject();
    for (auto it = buffers.begin(), end = buffers.end(); it != end; ++it)
        processJSONBuffer(it.key(), it.value().toObject());

    const QJsonObject views = m_json.object().value(KEY_BUFFER_VIEWS).toObject();
    loadBufferData();
    for (auto it = views.begin(), end = views.end(); it != end; ++it)
        processJSONBufferView(it.key(), it.value().toObject());
    unloadBufferData();

    const QJsonObject attrs = m_json.object().value(KEY_ACCESSORS).toObject();
    for (auto it = attrs.begin(), end = attrs.end(); it != end; ++it)
        processJSONAccessor(it.key(), it.value().toObject());

    const QJsonObject meshes = m_json.object().value(KEY_MESHES).toObject();
    for (auto it = meshes.begin(), end = meshes.end(); it != end && !m_geometry; ++it) {
        const QJsonObject &mesh = it.value().toObject();
        if (m_mesh.isEmpty() ||
            m_mesh.compare(mesh.value(KEY_NAME).toString(), Qt::CaseInsensitive) == 0)
            processJSONMesh(it.key(), mesh);
    }
}

void GLTFGeometryLoader::parseGLTF2()
{
    const QJsonArray buffers = m_json.object().value(KEY_BUFFERS).toArray();
    for (auto it = buffers.begin(), end = buffers.end(); it != end; ++it)
        processJSONBufferV2(it->toObject());

    const QJsonArray views = m_json.object().value(KEY_BUFFER_VIEWS).toArray();
    loadBufferDataV2();
    for (auto it = views.begin(), end = views.end(); it != end; ++it)
        processJSONBufferViewV2(it->toObject());
    unloadBufferDataV2();

    const QJsonArray attrs = m_json.object().value(KEY_ACCESSORS).toArray();
    for (auto it = attrs.begin(), end = attrs.end(); it != end; ++it)
        processJSONAccessorV2(it->toObject());

    const QJsonArray meshes = m_json.object().value(KEY_MESHES).toArray();
    for (auto it = meshes.begin(), end = meshes.end(); it != end && !m_geometry; ++it) {
        const QJsonObject &mesh = it->toObject();
        if (m_mesh.isEmpty() || m_mesh.compare(mesh.value(KEY_NAME).toString(), Qt::CaseInsensitive) == 0)
            processJSONMeshV2(mesh);
    }
}

void GLTFGeometryLoader::cleanup()
{
    m_geometry = nullptr;
    m_gltf1.m_accessorDict.clear();
    m_gltf1.m_buffers.clear();
}

void GLTFGeometryLoader::processJSONBuffer(const QString &id, const QJsonObject &json)
{
    // simply cache buffers for lookup by buffer-views
    m_gltf1.m_bufferDatas[id] = BufferData(json);
}

void GLTFGeometryLoader::processJSONBufferV2(const QJsonObject &json)
{
    // simply cache buffers for lookup by buffer-views
    m_gltf2.m_bufferDatas.push_back(BufferData(json));
}

void GLTFGeometryLoader::processJSONBufferView(const QString &id, const QJsonObject &json)
{
    QString bufName = json.value(KEY_BUFFER).toString();
    const auto it = qAsConst(m_gltf1.m_bufferDatas).find(bufName);
    if (Q_UNLIKELY(it == m_gltf1.m_bufferDatas.cend())) {
        qCWarning(GLTFGeometryLoaderLog, "unknown buffer: %ls processing view: %ls",
                  qUtf16PrintableImpl(bufName), qUtf16PrintableImpl(id));
        return;
    }
    const auto &bufferData = *it;

    int target = json.value(KEY_TARGET).toInt();

    switch (target) {
    case GL_ARRAY_BUFFER:
    case GL_ELEMENT_ARRAY_BUFFER:
        break;
    default:
        qCWarning(GLTFGeometryLoaderLog, "buffer %ls unsupported target: %d",
                  qUtf16PrintableImpl(id), target);
        return;
    }

    quint64 offset = 0;
    const auto byteOffset = json.value(KEY_BYTE_OFFSET);
    if (!byteOffset.isUndefined()) {
        offset = byteOffset.toInt();
        qCDebug(GLTFGeometryLoaderLog, "bv: %ls has offset: %lld", qUtf16PrintableImpl(id), offset);
    }

    const quint64 len = json.value(KEY_BYTE_LENGTH).toInt();

    QByteArray bytes = bufferData.data->mid(offset, len);
    if (Q_UNLIKELY(bytes.count() != int(len))) {
        qCWarning(GLTFGeometryLoaderLog, "failed to read sufficient bytes from: %ls for view %ls",
                  qUtf16PrintableImpl(bufferData.path), qUtf16PrintableImpl(id));
    }

    Qt3DRender::QBuffer *b = new Qt3DRender::QBuffer();
    b->setData(bytes);
    m_gltf1.m_buffers[id] = b;
}

void GLTFGeometryLoader::processJSONBufferViewV2(const QJsonObject &json)
{
    const int bufferIndex = json.value(KEY_BUFFER).toInt();
    if (Q_UNLIKELY(bufferIndex) >= m_gltf2.m_bufferDatas.size()) {
        qCWarning(GLTFGeometryLoaderLog, "unknown buffer: %d processing view", bufferIndex);
        return;
    }
    const auto bufferData = m_gltf2.m_bufferDatas[bufferIndex];

    int target = json.value(KEY_TARGET).toInt();
    switch (target) {
    case GL_ARRAY_BUFFER:
    case GL_ELEMENT_ARRAY_BUFFER:
        break;
    default:
        return;
    }

    quint64 offset = 0;
    const auto byteOffset = json.value(KEY_BYTE_OFFSET);
    if (!byteOffset.isUndefined()) {
        offset = byteOffset.toInt();
        qCDebug(GLTFGeometryLoaderLog, "bufferview has offset: %lld", offset);
    }

    const quint64 len = json.value(KEY_BYTE_LENGTH).toInt();
    QByteArray bytes = bufferData.data->mid(offset, len);
    if (Q_UNLIKELY(bytes.count() != int(len))) {
        qCWarning(GLTFGeometryLoaderLog, "failed to read sufficient bytes from: %ls for view",
                  qUtf16PrintableImpl(bufferData.path));
    }

    auto b = new Qt3DRender::QBuffer;
    b->setData(bytes);
    m_gltf2.m_buffers.push_back(b);
}

void GLTFGeometryLoader::processJSONAccessor(const QString &id, const QJsonObject &json)
{
    m_gltf1.m_accessorDict[id] = AccessorData(json);
}

void GLTFGeometryLoader::processJSONAccessorV2(const QJsonObject &json)
{
    m_gltf2.m_accessors.push_back(AccessorData(json));
}

void GLTFGeometryLoader::processJSONMesh(const QString &id, const QJsonObject &json)
{
    const QJsonArray primitivesArray = json.value(KEY_PRIMITIVES).toArray();
    for (const QJsonValue &primitiveValue : primitivesArray) {
        QJsonObject primitiveObject = primitiveValue.toObject();
        QString material = primitiveObject.value(KEY_MATERIAL).toString();

        if (Q_UNLIKELY(material.isEmpty())) {
            qCWarning(GLTFGeometryLoaderLog, "malformed primitive on %ls, missing material value %ls",
                      qUtf16PrintableImpl(id), qUtf16PrintableImpl(material));
            continue;
        }

        QGeometry *meshGeometry = new QGeometry;

        const QJsonObject attrs = primitiveObject.value(KEY_ATTRIBUTES).toObject();
        for (auto it = attrs.begin(), end = attrs.end(); it != end; ++it) {
            QString k = it.value().toString();
            const auto accessorIt = qAsConst(m_gltf1.m_accessorDict).find(k);
            if (Q_UNLIKELY(accessorIt == m_gltf1.m_accessorDict.cend())) {
                qCWarning(GLTFGeometryLoaderLog, "unknown attribute accessor: %ls on mesh %ls",
                          qUtf16PrintableImpl(k), qUtf16PrintableImpl(id));
                continue;
            }

            const QString attrName = it.key();
            QString attributeName = standardAttributeNameFromSemantic(attrName);
            if (attributeName.isEmpty())
                attributeName = attrName;

            //Get buffer handle for accessor
            Qt3DRender::QBuffer *buffer = m_gltf1.m_buffers.value(accessorIt->bufferViewName, nullptr);
            if (Q_UNLIKELY(!buffer)) {
                qCWarning(GLTFGeometryLoaderLog, "unknown buffer-view: %ls processing accessor: %ls",
                          qUtf16PrintableImpl(accessorIt->bufferViewName), qUtf16PrintableImpl(id));
                continue;
            }

            QAttribute *attribute = new QAttribute(buffer,
                                                   attributeName,
                                                   accessorIt->type,
                                                   accessorIt->dataSize,
                                                   accessorIt->count,
                                                   accessorIt->offset,
                                                   accessorIt->stride);
            attribute->setAttributeType(QAttribute::VertexAttribute);
            meshGeometry->addAttribute(attribute);
        }

        const auto indices = primitiveObject.value(KEY_INDICES);
        if (!indices.isUndefined()) {
            QString k = indices.toString();
            const auto accessorIt = qAsConst(m_gltf1.m_accessorDict).find(k);
            if (Q_UNLIKELY(accessorIt == m_gltf1.m_accessorDict.cend())) {
                qCWarning(GLTFGeometryLoaderLog, "unknown index accessor: %ls on mesh %ls",
                          qUtf16PrintableImpl(k), qUtf16PrintableImpl(id));
            } else {
                //Get buffer handle for accessor
                Qt3DRender::QBuffer *buffer = m_gltf1.m_buffers.value(accessorIt->bufferViewName, nullptr);
                if (Q_UNLIKELY(!buffer)) {
                    qCWarning(GLTFGeometryLoaderLog, "unknown buffer-view: %ls processing accessor: %ls",
                              qUtf16PrintableImpl(accessorIt->bufferViewName), qUtf16PrintableImpl(id));
                    continue;
                }

                QAttribute *attribute = new QAttribute(buffer,
                                                       accessorIt->type,
                                                       accessorIt->dataSize,
                                                       accessorIt->count,
                                                       accessorIt->offset,
                                                       accessorIt->stride);
                attribute->setAttributeType(QAttribute::IndexAttribute);
                meshGeometry->addAttribute(attribute);
            }
        } // of has indices

        m_geometry = meshGeometry;

        break;
    } // of primitives iteration
}

void GLTFGeometryLoader::processJSONMeshV2(const QJsonObject &json)
{
    const QJsonArray primitivesArray = json.value(KEY_PRIMITIVES).toArray();
    for (const QJsonValue &primitiveValue : primitivesArray) {
        QJsonObject primitiveObject = primitiveValue.toObject();

        QGeometry *meshGeometry = new QGeometry;

        const QJsonObject attrs = primitiveObject.value(KEY_ATTRIBUTES).toObject();
        for (auto it = attrs.begin(), end = attrs.end(); it != end; ++it) {
            const int accessorIndex = it.value().toInt();
            if (Q_UNLIKELY(accessorIndex >= m_gltf2.m_accessors.size())) {
                qCWarning(GLTFGeometryLoaderLog, "unknown attribute accessor: %d on mesh %ls",
                          accessorIndex, qUtf16PrintableImpl(json.value(KEY_NAME).toString()));
                continue;
            }
            const auto &accessor = m_gltf2.m_accessors[accessorIndex];

            const QString attrName = it.key();
            QString attributeName = standardAttributeNameFromSemantic(attrName);
            if (attributeName.isEmpty())
                attributeName = attrName;

            // Get buffer handle for accessor
            if (Q_UNLIKELY(accessor.bufferViewIndex >= m_gltf2.m_buffers.size())) {
                qCWarning(GLTFGeometryLoaderLog, "unknown buffer-view: %d processing accessor: %ls",
                          accessor.bufferViewIndex, qUtf16PrintableImpl(json.value(KEY_NAME).toString()));
                continue;
            }
            Qt3DRender::QBuffer *buffer = m_gltf2.m_buffers[accessor.bufferViewIndex];

            QAttribute *attribute = new QAttribute(buffer,
                                                   attributeName,
                                                   accessor.type,
                                                   accessor.dataSize,
                                                   accessor.count,
                                                   accessor.offset,
                                                   accessor.stride);
            attribute->setAttributeType(QAttribute::VertexAttribute);
            meshGeometry->addAttribute(attribute);
        }

        const auto indices = primitiveObject.value(KEY_INDICES);
        if (!indices.isUndefined()) {
            const int accessorIndex = indices.toInt();
            if (Q_UNLIKELY(accessorIndex >= m_gltf2.m_accessors.size())) {
                qCWarning(GLTFGeometryLoaderLog, "unknown index accessor: %d on mesh %ls",
                          accessorIndex, qUtf16PrintableImpl(json.value(KEY_NAME).toString()));
            } else {
                const auto &accessor = m_gltf2.m_accessors[accessorIndex];

                //Get buffer handle for accessor
                if (Q_UNLIKELY(accessor.bufferViewIndex >= m_gltf2.m_buffers.size())) {
                    qCWarning(GLTFGeometryLoaderLog, "unknown buffer-view: %d processing accessor: %ls",
                              accessor.bufferViewIndex, qUtf16PrintableImpl(json.value(KEY_NAME).toString()));
                    continue;
                }
                Qt3DRender::QBuffer *buffer = m_gltf2.m_buffers[accessor.bufferViewIndex];

                QAttribute *attribute = new QAttribute(buffer,
                                                       accessor.type,
                                                       accessor.dataSize,
                                                       accessor.count,
                                                       accessor.offset,
                                                       accessor.stride);
                attribute->setAttributeType(QAttribute::IndexAttribute);
                meshGeometry->addAttribute(attribute);
            }
        } // of has indices

        m_geometry = meshGeometry;

        break;
    } // of primitives iteration
}

void GLTFGeometryLoader::loadBufferData()
{
    for (auto &bufferData : m_gltf1.m_bufferDatas) {
        if (!bufferData.data) {
            bufferData.data = new QByteArray(resolveLocalData(bufferData.path));
        }
    }
}

void GLTFGeometryLoader::unloadBufferData()
{
    for (const auto &bufferData : qAsConst(m_gltf1.m_bufferDatas)) {
        QByteArray *data = bufferData.data;
        delete data;
    }
}

void GLTFGeometryLoader::loadBufferDataV2()
{
    for (auto &bufferData : m_gltf2.m_bufferDatas) {
        if (!bufferData.data)
            bufferData.data = new QByteArray(resolveLocalData(bufferData.path));
    }
}

void GLTFGeometryLoader::unloadBufferDataV2()
{
    for (const auto &bufferData : qAsConst(m_gltf2.m_bufferDatas)) {
        QByteArray *data = bufferData.data;
        delete data;
    }
}

QByteArray GLTFGeometryLoader::resolveLocalData(const QString &path) const
{
    QDir d(m_basePath);
    Q_ASSERT(d.exists());

    QString absPath = d.absoluteFilePath(path);
    QFile f(absPath);
    f.open(QIODevice::ReadOnly);
    return f.readAll();
}

QAttribute::VertexBaseType GLTFGeometryLoader::accessorTypeFromJSON(int componentType)
{
    if (componentType == GL_BYTE)
        return QAttribute::Byte;
    else if (componentType == GL_UNSIGNED_BYTE)
        return QAttribute::UnsignedByte;
    else if (componentType == GL_SHORT)
        return QAttribute::Short;
    else if (componentType == GL_UNSIGNED_SHORT)
        return QAttribute::UnsignedShort;
    else if (componentType == GL_UNSIGNED_INT)
        return QAttribute::UnsignedInt;
    else if (componentType == GL_FLOAT)
        return QAttribute::Float;

    //There shouldn't be an invalid case here
    qCWarning(GLTFGeometryLoaderLog, "unsupported accessor type %d", componentType);
    return QAttribute::Float;
}

uint GLTFGeometryLoader::accessorDataSizeFromJson(const QString &type)
{
    QString typeName = type.toUpper();
    if (typeName == QLatin1String("SCALAR"))
        return 1;
    if (typeName == QLatin1String("VEC2"))
        return 2;
    if (typeName == QLatin1String("VEC3"))
        return 3;
    if (typeName == QLatin1String("VEC4"))
        return 4;
    if (typeName == QLatin1String("MAT2"))
        return 4;
    if (typeName == QLatin1String("MAT3"))
        return 9;
    if (typeName == QLatin1String("MAT4"))
        return 16;

    return 0;
}

} // namespace Qt3DRender

QT_END_NAMESPACE
