/****************************************************************************
**
** Copyright (C) 2016 Research In Motion.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml 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 "qqmlinstantiator_p.h"
#include "qqmlinstantiator_p_p.h"
#include <QtQml/QQmlContext>
#include <QtQml/QQmlComponent>
#include <QtQml/QQmlInfo>
#include <QtQml/QQmlError>
#include <QtQmlModels/private/qqmlobjectmodel_p.h>
#if QT_CONFIG(qml_delegate_model)
#include <QtQmlModels/private/qqmldelegatemodel_p.h>
#endif

QT_BEGIN_NAMESPACE

QQmlInstantiatorPrivate::QQmlInstantiatorPrivate()
    : componentComplete(true)
    , effectiveReset(false)
    , active(true)
    , async(false)
#if QT_CONFIG(qml_delegate_model)
    , ownModel(false)
#endif
    , requestedIndex(-1)
    , model(QVariant(1))
    , instanceModel(nullptr)
    , delegate(nullptr)
{
}

QQmlInstantiatorPrivate::~QQmlInstantiatorPrivate()
{
    qDeleteAll(objects);
}

void QQmlInstantiatorPrivate::clear()
{
    Q_Q(QQmlInstantiator);
    if (!instanceModel)
        return;
    if (!objects.count())
        return;

    for (int i=0; i < objects.count(); i++) {
        q->objectRemoved(i, objects[i]);
        instanceModel->release(objects[i]);
    }
    objects.clear();
    q->objectChanged();
}

QObject *QQmlInstantiatorPrivate::modelObject(int index, bool async)
{
    requestedIndex = index;
    QObject *o = instanceModel->object(index, async ? QQmlIncubator::Asynchronous : QQmlIncubator::AsynchronousIfNested);
    requestedIndex = -1;
    return o;
}


void QQmlInstantiatorPrivate::regenerate()
{
    Q_Q(QQmlInstantiator);
    if (!componentComplete)
        return;

    int prevCount = q->count();

    clear();

    if (!active || !instanceModel || !instanceModel->count() || !instanceModel->isValid()) {
        if (prevCount)
            q->countChanged();
        return;
    }

    for (int i = 0; i < instanceModel->count(); i++) {
        QObject *object = modelObject(i, async);
        // If the item was already created we won't get a createdItem
        if (object)
            _q_createdItem(i, object);
    }
    if (q->count() != prevCount)
        q->countChanged();
}

void QQmlInstantiatorPrivate::_q_createdItem(int idx, QObject* item)
{
    Q_Q(QQmlInstantiator);
    if (objects.contains(item)) //Case when it was created synchronously in regenerate
        return;
    if (requestedIndex != idx) // Asynchronous creation, reference the object
        (void)instanceModel->object(idx);
    item->setParent(q);
    if (objects.size() < idx + 1) {
        int modelCount = instanceModel->count();
        if (objects.capacity() < modelCount)
            objects.reserve(modelCount);
        objects.resize(idx + 1);
    }
    if (QObject *o = objects.at(idx))
        instanceModel->release(o);
    objects.replace(idx, item);
    if (objects.count() == 1)
        q->objectChanged();
    q->objectAdded(idx, item);
}

void QQmlInstantiatorPrivate::_q_modelUpdated(const QQmlChangeSet &changeSet, bool reset)
{
    Q_Q(QQmlInstantiator);

    if (!componentComplete || effectiveReset)
        return;

    if (reset) {
        regenerate();
        if (changeSet.difference() != 0)
            q->countChanged();
        return;
    }

    int difference = 0;
    QHash<int, QVector<QPointer<QObject> > > moved;
    const QVector<QQmlChangeSet::Change> &removes = changeSet.removes();
    for (const QQmlChangeSet::Change &remove : removes) {
        int index = qMin(remove.index, objects.count());
        int count = qMin(remove.index + remove.count, objects.count()) - index;
        if (remove.isMove()) {
            moved.insert(remove.moveId, objects.mid(index, count));
            objects.erase(
                    objects.begin() + index,
                    objects.begin() + index + count);
        } else while (count--) {
            QObject *obj = objects.at(index);
            objects.remove(index);
            q->objectRemoved(index, obj);
            if (obj)
                instanceModel->release(obj);
        }

        difference -= remove.count;
    }

    const QVector<QQmlChangeSet::Change> &inserts = changeSet.inserts();
    for (const QQmlChangeSet::Change &insert : inserts) {
        int index = qMin(insert.index, objects.count());
        if (insert.isMove()) {
            QVector<QPointer<QObject> > movedObjects = moved.value(insert.moveId);
            objects = objects.mid(0, index) + movedObjects + objects.mid(index);
        } else {
            if (insert.index <= objects.size())
                objects.insert(insert.index, insert.count, nullptr);
            for (int i = 0; i < insert.count; ++i) {
                int modelIndex = index + i;
                QObject* obj = modelObject(modelIndex, async);
                if (obj)
                    _q_createdItem(modelIndex, obj);
            }
        }
        difference += insert.count;
    }

    if (difference != 0)
        q->countChanged();
}

#if QT_CONFIG(qml_delegate_model)
void QQmlInstantiatorPrivate::makeModel()
{
    Q_Q(QQmlInstantiator);
    QQmlDelegateModel* delegateModel = new QQmlDelegateModel(qmlContext(q), q);
    instanceModel = delegateModel;
    ownModel = true;
    delegateModel->setDelegate(delegate);
    delegateModel->classBegin(); //Pretend it was made in QML
    if (componentComplete)
        delegateModel->componentComplete();
}
#endif


/*!
    \qmltype Instantiator
    \instantiates QQmlInstantiator
    \inqmlmodule QtQml.Models
    \ingroup qtquick-models
    \brief Dynamically creates objects.

    A Instantiator can be used to control the dynamic creation of objects, or to dynamically
    create multiple objects from a template.

    The Instantiator element will manage the objects it creates. Those objects are parented to the
    Instantiator and can also be deleted by the Instantiator if the Instantiator's properties change. Objects
    can also be destroyed dynamically through other means, and the Instantiator will not recreate
    them unless the properties of the Instantiator change.

    \note Instantiator is part of QtQml.Models since version 2.14 and part of QtQml since
    version 2.1. Importing Instantiator via QtQml is deprecated since Qt 5.14.
*/
QQmlInstantiator::QQmlInstantiator(QObject *parent)
    : QObject(*(new QQmlInstantiatorPrivate), parent)
{
}

QQmlInstantiator::~QQmlInstantiator()
{
}

/*!
    \qmlsignal QtQml::Instantiator::objectAdded(int index, QtObject object)

    This signal is emitted when an object is added to the Instantiator. The \a index
    parameter holds the index which the object has been given, and the \a object
    parameter holds the \l QtObject that has been added.
*/

/*!
    \qmlsignal QtQml::Instantiator::objectRemoved(int index, QtObject object)

    This signal is emitted when an object is removed from the Instantiator. The \a index
    parameter holds the index which the object had been given, and the \a object
    parameter holds the \l QtObject that has been removed.

    Do not keep a reference to \a object if it was created by this Instantiator, as
    in these cases it will be deleted shortly after the signal is handled.
*/
/*!
    \qmlproperty bool QtQml::Instantiator::active

    When active is true, and the delegate component is ready, the Instantiator will
    create objects according to the model. When active is false, no objects
    will be created and any previously created objects will be destroyed.

    Default is true.
*/
bool QQmlInstantiator::isActive() const
{
    Q_D(const QQmlInstantiator);
    return d->active;
}

void QQmlInstantiator::setActive(bool newVal)
{
    Q_D(QQmlInstantiator);
    if (newVal == d->active)
        return;
    d->active = newVal;
    emit activeChanged();
    d->regenerate();
}

/*!
    \qmlproperty bool QtQml::Instantiator::asynchronous

    When asynchronous is true the Instantiator will attempt to create objects
    asynchronously. This means that objects may not be available immediately,
    even if active is set to true.

    You can use the objectAdded signal to respond to items being created.

    Default is false.
*/
bool QQmlInstantiator::isAsync() const
{
    Q_D(const QQmlInstantiator);
    return d->async;
}

void QQmlInstantiator::setAsync(bool newVal)
{
    Q_D(QQmlInstantiator);
    if (newVal == d->async)
        return;
    d->async = newVal;
    emit asynchronousChanged();
}


/*!
    \qmlproperty int QtQml::Instantiator::count

    The number of objects the Instantiator is currently managing.
*/

int QQmlInstantiator::count() const
{
    Q_D(const QQmlInstantiator);
    return d->objects.count();
}

/*!
    \qmlproperty QtQml::Component QtQml::Instantiator::delegate
    \default

    The component used to create all objects.

    Note that an extra variable, index, will be available inside instances of the
    delegate. This variable refers to the index of the instance inside the Instantiator,
    and can be used to obtain the object through the objectAt method of the Instantiator.

    If this property is changed, all instances using the old delegate will be destroyed
    and new instances will be created using the new delegate.
*/
QQmlComponent* QQmlInstantiator::delegate()
{
    Q_D(QQmlInstantiator);
    return d->delegate;
}

void QQmlInstantiator::setDelegate(QQmlComponent* c)
{
    Q_D(QQmlInstantiator);
    if (c == d->delegate)
        return;

    d->delegate = c;
    emit delegateChanged();

#if QT_CONFIG(qml_delegate_model)
    if (!d->ownModel)
        return;

    if (QQmlDelegateModel *dModel = qobject_cast<QQmlDelegateModel*>(d->instanceModel))
        dModel->setDelegate(c);
    if (d->componentComplete)
        d->regenerate();
#endif
}

/*!
    \qmlproperty variant QtQml::Instantiator::model

    This property can be set to any of the supported \l {qml-data-models}{data models}:

    \list
    \li A number that indicates the number of delegates to be created by the repeater
    \li A model (e.g. a ListModel item, or a QAbstractItemModel subclass)
    \li A string list
    \li An object list
    \endlist

    The type of model affects the properties that are exposed to the \l delegate.

    Default value is 1, which creates a single delegate instance.

    \sa {qml-data-models}{Data Models}
*/

QVariant QQmlInstantiator::model() const
{
    Q_D(const QQmlInstantiator);
    return d->model;
}

void QQmlInstantiator::setModel(const QVariant &v)
{
    Q_D(QQmlInstantiator);
    if (d->model == v)
        return;

    d->model = v;
    //Don't actually set model until componentComplete in case it wants to create its delegates immediately
    if (!d->componentComplete)
        return;

    QQmlInstanceModel *prevModel = d->instanceModel;
    QObject *object = qvariant_cast<QObject*>(v);
    QQmlInstanceModel *vim = nullptr;
    if (object && (vim = qobject_cast<QQmlInstanceModel *>(object))) {
#if QT_CONFIG(qml_delegate_model)
        if (d->ownModel) {
            delete d->instanceModel;
            prevModel = nullptr;
            d->ownModel = false;
        }
#endif
        d->instanceModel = vim;
#if QT_CONFIG(qml_delegate_model)
    } else if (v != QVariant(0)){
        if (!d->ownModel)
            d->makeModel();

        if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel *>(d->instanceModel)) {
            d->effectiveReset = true;
            dataModel->setModel(v);
            d->effectiveReset = false;
        }
#endif
    }

    if (d->instanceModel != prevModel) {
        if (prevModel) {
            disconnect(prevModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
                    this, SLOT(_q_modelUpdated(QQmlChangeSet,bool)));
            disconnect(prevModel, SIGNAL(createdItem(int,QObject*)), this, SLOT(_q_createdItem(int,QObject*)));
            //disconnect(prevModel, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
        }

        if (d->instanceModel) {
            connect(d->instanceModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
                    this, SLOT(_q_modelUpdated(QQmlChangeSet,bool)));
            connect(d->instanceModel, SIGNAL(createdItem(int,QObject*)), this, SLOT(_q_createdItem(int,QObject*)));
            //connect(d->instanceModel, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
        }
    }

    d->regenerate();
    emit modelChanged();
}

/*!
    \qmlproperty QtObject QtQml::Instantiator::object

    This is a reference to the first created object, intended as a convenience
    for the case where only one object has been created.
*/
QObject *QQmlInstantiator::object() const
{
    Q_D(const QQmlInstantiator);
    if (d->objects.count())
        return d->objects[0];
    return nullptr;
}

/*!
    \qmlmethod QtObject QtQml::Instantiator::objectAt(int index)

    Returns a reference to the object with the given \a index.
*/
QObject *QQmlInstantiator::objectAt(int index) const
{
    Q_D(const QQmlInstantiator);
    if (index >= 0 && index < d->objects.count())
        return d->objects[index];
    return nullptr;
}

/*!
 \internal
*/
void QQmlInstantiator::classBegin()
{
    Q_D(QQmlInstantiator);
    d->componentComplete = false;
}

/*!
 \internal
*/
void QQmlInstantiator::componentComplete()
{
    Q_D(QQmlInstantiator);
    d->componentComplete = true;
#if QT_CONFIG(qml_delegate_model)
    if (d->ownModel) {
        static_cast<QQmlDelegateModel*>(d->instanceModel)->componentComplete();
        d->regenerate();
    } else
#endif
    {
        QVariant realModel = d->model;
        d->model = QVariant(0);
        setModel(realModel); //If realModel == d->model this won't do anything, but that's fine since the model's 0
        //setModel calls regenerate
    }
}

QT_END_NAMESPACE

#include "moc_qqmlinstantiator_p.cpp"
