/****************************************************************************
**
** Copyright (C) 2017 Ford Motor Company
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtRemoteObjects 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 "qremoteobjectabstractitemmodelreplica.h"
#include "qremoteobjectabstractitemmodelreplica_p.h"

#include "qremoteobjectnode.h"

#include <QtCore/qdebug.h>
#include <QtCore/qrect.h>
#include <QtCore/qpoint.h>

QT_BEGIN_NAMESPACE

inline QDebug operator<<(QDebug stream, const RequestedData &data)
{
    return stream.nospace() << "RequestedData[start=" << data.start << ", end=" << data.end << ", roles=" << data.roles << "]";
}

CacheData::CacheData(QAbstractItemModelReplicaImplementation *model, CacheData *parentItem)
    : replicaModel(model)
    , parent(parentItem)
    , hasChildren(false)
    , columnCount(0)
    , rowCount(0)
{
    if (parent)
        replicaModel->m_activeParents.insert(parent);
}

CacheData::~CacheData() {
    if (parent && !replicaModel->m_activeParents.empty())
        replicaModel->m_activeParents.erase(this);
}

QAbstractItemModelReplicaImplementation::QAbstractItemModelReplicaImplementation()
    : QRemoteObjectReplica()
    , m_selectionModel(0)
    , m_rootItem(this)
{
    QAbstractItemModelReplicaImplementation::registerMetatypes();
    initializeModelConnections();
    connect(this, &QAbstractItemModelReplicaImplementation::availableRolesChanged, this, [this]{
        m_availableRoles.clear();
    });
}

QAbstractItemModelReplicaImplementation::QAbstractItemModelReplicaImplementation(QRemoteObjectNode *node, const QString &name)
    : QRemoteObjectReplica(ConstructWithNode)
    , m_selectionModel(0)
    , m_rootItem(this)
{
    QAbstractItemModelReplicaImplementation::registerMetatypes();
    initializeModelConnections();
    initializeNode(node, name);
    connect(this, &QAbstractItemModelReplicaImplementation::availableRolesChanged, this, [this]{
        m_availableRoles.clear();
    });
}

QAbstractItemModelReplicaImplementation::~QAbstractItemModelReplicaImplementation()
{
    m_rootItem.clear();
    qDeleteAll(m_pendingRequests);
}

void QAbstractItemModelReplicaImplementation::initialize()
{
    QVariantList properties;
    properties << QVariant::fromValue(QVector<int>());
    properties << QVariant::fromValue(QIntHash());
    setProperties(properties);
}

void QAbstractItemModelReplicaImplementation::registerMetatypes()
{
    static bool alreadyRegistered = false;
    if (alreadyRegistered)
        return;

    alreadyRegistered = true;
    qRegisterMetaType<QAbstractItemModel*>();
    qRegisterMetaType<Qt::Orientation>();
    qRegisterMetaType<QVector<Qt::Orientation> >();
    qRegisterMetaTypeStreamOperators<ModelIndex>();
    qRegisterMetaTypeStreamOperators<IndexList>();
    qRegisterMetaTypeStreamOperators<DataEntries>();
    qRegisterMetaTypeStreamOperators<MetaAndDataEntries>();
    qRegisterMetaTypeStreamOperators<Qt::Orientation>();
    qRegisterMetaTypeStreamOperators<QVector<Qt::Orientation> >();
    qRegisterMetaTypeStreamOperators<QItemSelectionModel::SelectionFlags>();
    qRegisterMetaType<QItemSelectionModel::SelectionFlags>();
    qRegisterMetaType<QSize>();
    qRegisterMetaType<QIntHash>();
    qRegisterMetaTypeStreamOperators<QIntHash>();
}

void QAbstractItemModelReplicaImplementation::initializeModelConnections()
{
    connect(this, &QAbstractItemModelReplicaImplementation::dataChanged, this, &QAbstractItemModelReplicaImplementation::onDataChanged);
    connect(this, &QAbstractItemModelReplicaImplementation::rowsInserted, this, &QAbstractItemModelReplicaImplementation::onRowsInserted);
    connect(this, &QAbstractItemModelReplicaImplementation::columnsInserted, this, &QAbstractItemModelReplicaImplementation::onColumnsInserted);
    connect(this, &QAbstractItemModelReplicaImplementation::rowsRemoved, this, &QAbstractItemModelReplicaImplementation::onRowsRemoved);
    connect(this, &QAbstractItemModelReplicaImplementation::rowsMoved, this, &QAbstractItemModelReplicaImplementation::onRowsMoved);
    connect(this, &QAbstractItemModelReplicaImplementation::currentChanged, this, &QAbstractItemModelReplicaImplementation::onCurrentChanged);
    connect(this, &QAbstractItemModelReplicaImplementation::modelReset, this, &QAbstractItemModelReplicaImplementation::onModelReset);
    connect(this, &QAbstractItemModelReplicaImplementation::headerDataChanged, this, &QAbstractItemModelReplicaImplementation::onHeaderDataChanged);
}

inline void removeIndexFromRow(const QModelIndex &index, const QVector<int> &roles, CachedRowEntry *entry)
{
    CachedRowEntry &entryRef = *entry;
    if (index.column() < entryRef.size()) {
        CacheEntry &entry = entryRef[index.column()];
        if (roles.isEmpty()) {
            entry.data.clear();
        } else {
            for (int role : roles)
                entry.data.remove(role);
        }
    }
}

void QAbstractItemModelReplicaImplementation::onReplicaCurrentChanged(const QModelIndex &current, const QModelIndex &previous)
{
    Q_UNUSED(previous)
    IndexList currentIndex = toModelIndexList(current, q);
    qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "current=" << currentIndex;
    replicaSetCurrentIndex(currentIndex, QItemSelectionModel::Clear|QItemSelectionModel::Select|QItemSelectionModel::Current);
}

void QAbstractItemModelReplicaImplementation::setModel(QAbstractItemModelReplica *model)
{
    q = model;
    setParent(model);
    m_selectionModel.reset(new QItemSelectionModel(model));
    connect(m_selectionModel.data(), &QItemSelectionModel::currentChanged, this, &QAbstractItemModelReplicaImplementation::onReplicaCurrentChanged);
}

bool QAbstractItemModelReplicaImplementation::clearCache(const IndexList &start, const IndexList &end, const QVector<int> &roles = QVector<int>())
{
    Q_ASSERT(start.size() == end.size());

    bool ok = true;
    const QModelIndex startIndex = toQModelIndex(start, q, &ok);
    if (!ok)
        return false;
    const QModelIndex endIndex = toQModelIndex(end, q, &ok);
    if (!ok)
        return false;
    Q_ASSERT(startIndex.isValid());
    Q_ASSERT(endIndex.isValid());
    Q_ASSERT(startIndex.parent() == endIndex.parent());
    Q_UNUSED(endIndex);
    QModelIndex parentIndex = startIndex.parent();
    auto parentItem = cacheData(parentIndex);

    const int startRow = start.last().row;
    const int lastRow = end.last().row;
    const int startColumn = start.last().column;
    const int lastColumn = end.last().column;
    for (int row = startRow; row <= lastRow; ++row) {
        Q_ASSERT_X(row >= 0 && row < parentItem->rowCount, __FUNCTION__, qPrintable(QString(QLatin1String("0 <= %1 < %2")).arg(row).arg(parentItem->rowCount)));
        auto item = parentItem->children.get(row);
        if (item) {
            CachedRowEntry *entry = &(item->cachedRowEntry);
            for (int column = startColumn; column <= lastColumn; ++column)
                removeIndexFromRow(q->index(row, column, parentIndex), roles, entry);
        }
    }
    return true;
}

void QAbstractItemModelReplicaImplementation::onDataChanged(const IndexList &start, const IndexList &end, const QVector<int> &roles)
{
    qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "start=" << start << "end=" << end << "roles=" << roles;

    // we need to clear the cache to make sure the new remote data is fetched if the new data call is happening
    if (clearCache(start, end, roles)) {
        bool ok = true;
        const QModelIndex startIndex = toQModelIndex(start, q, &ok);
        if (!ok)
            return;
        const QModelIndex endIndex = toQModelIndex(end, q, &ok);
        if (!ok)
            return;
        Q_ASSERT(startIndex.parent() == endIndex.parent());
        auto parentItem = cacheData(startIndex.parent());
        int startRow = start.last().row;
        int endRow = end.last().row;
        bool dataChanged = false;
        while (startRow <= endRow) {
            for (;startRow <= endRow; startRow++) {
                if (parentItem->children.exists(startRow))
                    break;
            }

            if (startRow  > endRow)
                break;

            RequestedData data;
            data.roles = roles;
            data.start = start;
            data.start.last().row = startRow;

            while (startRow <= endRow && parentItem->children.exists(startRow))
                ++startRow;

            data.end = end;
            data.end.last().row = startRow -1;

            m_requestedData.append(data);
            dataChanged = true;
        }

        if (dataChanged)
            QMetaObject::invokeMethod(this, "fetchPendingData", Qt::QueuedConnection);
    }
}

void QAbstractItemModelReplicaImplementation::onRowsInserted(const IndexList &parent, int start, int end)
{
    qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "start=" << start << "end=" << end << "parent=" << parent;

    bool treeFullyLazyLoaded = true;
    const QModelIndex parentIndex = toQModelIndex(parent, q, &treeFullyLazyLoaded, true);
    if (!treeFullyLazyLoaded)
        return;

    auto parentItem = cacheData(parentIndex);
    q->beginInsertRows(parentIndex, start, end);
    parentItem->insertChildren(start, end);
    q->endInsertRows();
    if (!parentItem->hasChildren && parentItem->columnCount > 0) {
        parentItem->hasChildren = true;
        emit q->dataChanged(parentIndex, parentIndex);
    }
}

void QAbstractItemModelReplicaImplementation::onColumnsInserted(const IndexList &parent, int start, int end)
{
    qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "start=" << start << "end=" << end << "parent=" << parent;

    bool treeFullyLazyLoaded = true;
    const QModelIndex parentIndex = toQModelIndex(parent, q, &treeFullyLazyLoaded);
    if (!treeFullyLazyLoaded)
        return;

    //Since we need to support QAIM and models that don't emit columnCountChanged
    //check if we have a constant columnCount everywhere if thats the case don't insert
    //more columns
    auto parentItem = cacheData(parentIndex);
    auto parentOfParent = parentItem->parent;
    if (parentOfParent && parentItem != &m_rootItem)
        if (parentOfParent->columnCount == parentItem->columnCount)
            return;
    q->beginInsertColumns(parentIndex, start, end);
    parentItem->columnCount += end - start + 1;
    q->endInsertColumns();
    if (!parentItem->hasChildren && parentItem->children.size() > 0) {
        parentItem->hasChildren = true;
        emit q->dataChanged(parentIndex, parentIndex);
    }

}

void QAbstractItemModelReplicaImplementation::onRowsRemoved(const IndexList &parent, int start, int end)
{
    qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "start=" << start << "end=" << end << "parent=" << parent;

    bool treeFullyLazyLoaded = true;
    const QModelIndex parentIndex = toQModelIndex(parent, q, &treeFullyLazyLoaded);
    if (!treeFullyLazyLoaded)
        return;

    auto parentItem = cacheData(parentIndex);
    q->beginRemoveRows(parentIndex, start, end);
    if (parentItem)
        parentItem->removeChildren(start, end);
    q->endRemoveRows();
}

void QAbstractItemModelReplicaImplementation::onRowsMoved(IndexList srcParent, int srcRow, int count, IndexList destParent, int destRow)
{
    qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO;

    const QModelIndex sourceParent = toQModelIndex(srcParent, q);
    const QModelIndex destinationParent = toQModelIndex(destParent, q);
    Q_ASSERT(!sourceParent.isValid());
    Q_ASSERT(!destinationParent.isValid());
    q->beginMoveRows(sourceParent, srcRow, count, destinationParent, destRow);
//TODO misses parents...
    IndexList start, end;
    start << ModelIndex(srcRow, 0);
    end << ModelIndex(srcRow + count, q->columnCount(sourceParent)-1);
    clearCache(start, end);
    IndexList start2, end2;
    start2 << ModelIndex(destRow, 0);
    end2 << ModelIndex(destRow + count, q->columnCount(destinationParent)-1);
    clearCache(start2, end2);
    q->endMoveRows();
}

void QAbstractItemModelReplicaImplementation::onCurrentChanged(IndexList current, IndexList previous)
{
    qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "current=" << current << "previous=" << previous;
    Q_UNUSED(previous);
    Q_ASSERT(m_selectionModel);
    bool ok;
    // If we have several tree models sharing a selection model, we
    // can't guarantee that all Replicas have the selected cell
    // available.
    const QModelIndex currentIndex = toQModelIndex(current, q, &ok);
    // Ignore selection if we can't find the desired cell.
    if (ok)
        m_selectionModel->setCurrentIndex(currentIndex, QItemSelectionModel::Clear|QItemSelectionModel::Select|QItemSelectionModel::Current);
}

void QAbstractItemModelReplicaImplementation::handleInitDone(QRemoteObjectPendingCallWatcher *watcher)
{
    qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO;

    handleModelResetDone(watcher);
    m_initDone = true;
    emit q->initialized();
}

void QAbstractItemModelReplicaImplementation::handleModelResetDone(QRemoteObjectPendingCallWatcher *watcher)
{
    QSize size;
    if (m_initialAction == QtRemoteObjects::FetchRootSize)
        size = watcher->returnValue().toSize();
    else {
        Q_ASSERT(watcher->returnValue().canConvert<MetaAndDataEntries>());
        size = watcher->returnValue().value<MetaAndDataEntries>().size;
    }

    qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "size=" << size;

    q->beginResetModel();
    m_rootItem.clear();
    if (size.height() > 0) {
        m_rootItem.rowCount = size.height();
        m_rootItem.hasChildren = true;
    }

    m_rootItem.columnCount = size.width();
    m_headerData[0].resize(size.width());
    m_headerData[1].resize(size.height());
    if (m_initialAction == QtRemoteObjects::PrefetchData) {
        auto entries = watcher->returnValue().value<MetaAndDataEntries>();
        for (int i = 0; i < entries.data.size(); ++i)
            fillCache(entries.data[i], entries.roles);
    }
    q->endResetModel();
    m_pendingRequests.removeAll(watcher);
    delete watcher;
}

void QAbstractItemModelReplicaImplementation::handleSizeDone(QRemoteObjectPendingCallWatcher *watcher)
{
    SizeWatcher *sizeWatcher = static_cast<SizeWatcher*>(watcher);
    const QSize size = sizeWatcher->returnValue().toSize();
    auto parentItem = cacheData(sizeWatcher->parentList);
    const QModelIndex parent = toQModelIndex(sizeWatcher->parentList, q);

    if (size.width() != parentItem->columnCount) {
        const int columnCount = std::max(0, parentItem->columnCount);
        Q_ASSERT_X(size.width() >= parentItem->columnCount, __FUNCTION__, "The column count should only shrink in columnsRemoved!!");
        parentItem->columnCount = size.width();
        if (size.width() > columnCount) {
            Q_ASSERT(size.width() > 0);
            q->beginInsertColumns(parent, columnCount, size.width() - 1);
            q->endInsertColumns();
        } else {
            Q_ASSERT_X(size.width() == columnCount, __FUNCTION__, qPrintable(QString(QLatin1String("%1 != %2")).arg(size.width()).arg(columnCount)));
        }
    }

    Q_ASSERT_X(size.height() >= parentItem->rowCount, __FUNCTION__, "The new size and the current size should match!!");
    if (!parentItem->rowCount) {
        if (size.height() > 0) {
            q->beginInsertRows(parent, 0, size.height() - 1);
            parentItem->rowCount = size.height();
            q->endInsertRows();
        }
    } else {
        Q_ASSERT_X(parentItem->rowCount == size.height(), __FUNCTION__, qPrintable(QString(QLatin1String("%1 != %2")).arg(parentItem->rowCount).arg(size.height())));
    }
    m_pendingRequests.removeAll(watcher);
    delete watcher;
}

void QAbstractItemModelReplicaImplementation::init()
{
    qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << this->node()->objectName();
    QRemoteObjectPendingCallWatcher *watcher = doModelReset();
    connect(watcher, &QRemoteObjectPendingCallWatcher::finished, this, &QAbstractItemModelReplicaImplementation::handleInitDone);
}

QRemoteObjectPendingCallWatcher* QAbstractItemModelReplicaImplementation::doModelReset()
{
    qDeleteAll(m_pendingRequests);
    m_pendingRequests.clear();
    IndexList parentList;
    QRemoteObjectPendingCallWatcher *watcher;
    if (m_initialAction == QtRemoteObjects::FetchRootSize) {
        auto call = replicaSizeRequest(parentList);
        watcher = new SizeWatcher(parentList, call);
    } else {
        auto call = replicaCacheRequest(m_rootItem.children.cacheSize, m_initialFetchRolesHint);
        watcher = new QRemoteObjectPendingCallWatcher(call);
    }
    m_pendingRequests.push_back(watcher);
    return watcher;
}

inline void fillCacheEntry(CacheEntry *entry, const IndexValuePair &pair, const QVector<int> &roles)
{
    Q_ASSERT(entry);

    const QVariantList &data = pair.data;
    Q_ASSERT(roles.size() == data.size());

    entry->flags = pair.flags;

    qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "data.size=" << data.size();
    for (int i = 0; i < data.size(); ++i) {
        const int role = roles[i];
        const QVariant dataVal = data[i];
        qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "role=" << role << "data=" << dataVal;
        entry->data[role] = dataVal;
    }
}

inline void fillRow(CacheData *item, const IndexValuePair &pair, const QAbstractItemModel *model, const QVector<int> &roles)
{
    CachedRowEntry &rowRef = item->cachedRowEntry;
    const QModelIndex index = toQModelIndex(pair.index, model);
    Q_ASSERT(index.isValid());
    qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "row=" << index.row() << "column=" << index.column();
    if (index.column() == 0)
        item->hasChildren = pair.hasChildren;
    bool existed = false;
    for (int i = 0; i < rowRef.size(); ++i) {
        if (i == index.column()) {
            fillCacheEntry(&rowRef[i], pair, roles);
            existed = true;
        }
    }
    qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "existed=" << existed;
    if (!existed) {
        CacheEntry entries;
        fillCacheEntry(&entries, pair, roles);
        rowRef.append(entries);
    }
}

int collectEntriesForRow(DataEntries* filteredEntries, int row, const DataEntries &entries, int startIndex)
{
    Q_ASSERT(filteredEntries);
    const int size = entries.data.size();
    for (int i = startIndex; i < size; ++i)
    {
        const IndexValuePair &pair = entries.data[i];
        if (pair.index.last().row == row)
            filteredEntries->data << pair;
        else
            return i;
    }
    return size;
}

void QAbstractItemModelReplicaImplementation::fillCache(const IndexValuePair &pair, const QVector<int> &roles)
{
    if (auto item = createCacheData(pair.index)) {
        fillRow(item, pair, q, roles);
        item->rowCount = pair.size.height();
        item->columnCount = pair.size.width();
    }
    for (const auto &it : pair.children)
        fillCache(it, roles);
}

void QAbstractItemModelReplicaImplementation::requestedData(QRemoteObjectPendingCallWatcher *qobject)
{
    RowWatcher *watcher = static_cast<RowWatcher *>(qobject);
    Q_ASSERT(watcher);
    Q_ASSERT(watcher->start.size() == watcher->end.size());

    qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "start=" << watcher->start << "end=" << watcher->end;

    IndexList parentList = watcher->start;
    Q_ASSERT(!parentList.isEmpty());
    parentList.pop_back();
    auto parentItem = cacheData(parentList);
    DataEntries entries = watcher->returnValue().value<DataEntries>();

    const int rowCount = parentItem->rowCount;
    const int columnCount = parentItem->columnCount;

    if (rowCount < 1 || columnCount < 1)
        return;

    const int startRow =  std::min(watcher->start.last().row, rowCount - 1);
    const int endRow = std::min(watcher->end.last().row, rowCount - 1);
    const int startColumn = std::min(watcher->start.last().column, columnCount - 1);
    const int endColumn = std::min(watcher->end.last().column, columnCount - 1);
    Q_ASSERT_X(startRow >= 0 && startRow < parentItem->rowCount, __FUNCTION__, qPrintable(QString(QLatin1String("0 <= %1 < %2")).arg(startRow).arg(parentItem->rowCount)));
    Q_ASSERT_X(endRow >= 0 && endRow < parentItem->rowCount, __FUNCTION__, qPrintable(QString(QLatin1String("0 <= %1 < %2")).arg(endRow).arg(parentItem->rowCount)));

    for (int i = 0; i < entries.data.size(); ++i) {
        IndexValuePair pair = entries.data[i];
        if (auto item = createCacheData(pair.index))
            fillRow(item, pair, q, watcher->roles);
    }

    const QModelIndex parentIndex = toQModelIndex(parentList, q);
    const QModelIndex startIndex = q->index(startRow, startColumn, parentIndex);
    const QModelIndex endIndex = q->index(endRow, endColumn, parentIndex);
    Q_ASSERT(startIndex.isValid());
    Q_ASSERT(endIndex.isValid());
    emit q->dataChanged(startIndex, endIndex, watcher->roles);
    m_pendingRequests.removeAll(watcher);
    delete watcher;
}

void QAbstractItemModelReplicaImplementation::fetchPendingData()
{
    if (m_requestedData.isEmpty())
        return;

    qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "m_requestedData.size=" << m_requestedData.size();

    std::vector<RequestedData> finalRequests;
    RequestedData curData;
    for (const RequestedData &data : qExchange(m_requestedData, {})) {
        qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "REQUESTED start=" << data.start << "end=" << data.end << "roles=" << data.roles;

        Q_ASSERT(!data.start.isEmpty());
        Q_ASSERT(!data.end.isEmpty());
        Q_ASSERT(data.start.size() == data.end.size());
        if (curData.start.isEmpty() || curData.start.last().row == -1 || curData.start.last().column == -1)
            curData = data;
        if (curData.start.size() != data.start.size()) {
            finalRequests.push_back(curData);
            curData = data;
        } else {
            if (data.start.size() > 1) {
                for (int i = 0; i < data.start.size() - 1; ++i) {
                    if (curData.start[i].row != data.start[i].row ||
                        curData.start[i].column != data.start[i].column) {
                        finalRequests.push_back(curData);
                        curData = data;
                    }
                }
            }

            const ModelIndex curIndStart = curData.start.last();
            const ModelIndex curIndEnd = curData.end.last();
            const ModelIndex dataIndStart = data.start.last();
            const ModelIndex dataIndEnd = data.end.last();
            const ModelIndex resStart(std::min(curIndStart.row, dataIndStart.row), std::min(curIndStart.column, dataIndStart.column));
            const ModelIndex resEnd(std::max(curIndEnd.row, dataIndEnd.row), std::max(curIndEnd.column, dataIndEnd.column));
            QVector<int> roles = curData.roles;
            if (!curData.roles.isEmpty()) {
                for (int role : data.roles) {
                    if (!curData.roles.contains(role))
                        roles.append(role);
                }
            }
            QRect firstRect( QPoint(curIndStart.row, curIndStart.column), QPoint(curIndEnd.row, curIndEnd.column));
            QRect secondRect( QPoint(dataIndStart.row, dataIndStart.column), QPoint(dataIndEnd.row, dataIndEnd.column));

            const bool borders = (qAbs(curIndStart.row - dataIndStart.row) == 1) ||
                                 (qAbs(curIndStart.column - dataIndStart.column) == 1) ||
                                 (qAbs(curIndEnd.row - dataIndEnd.row) == 1) ||
                                 (qAbs(curIndEnd.column - dataIndEnd.column) == 1);

            if ((resEnd.row - resStart.row < 100) && (firstRect.intersects(secondRect) || borders)) {
                IndexList start = curData.start;
                start.pop_back();
                start.push_back(resStart);
                IndexList end = curData.end;
                end.pop_back();
                end.push_back(resEnd);
                curData.start = start;
                curData.end = end;
                curData.roles = roles;
                Q_ASSERT(!start.isEmpty());
                Q_ASSERT(!end.isEmpty());
            } else {
                finalRequests.push_back(curData);
                curData = data;
            }
        }
    }
    finalRequests.push_back(curData);
    //qCDebug(QT_REMOTEOBJECT_MODELS) << "Final requests" << finalRequests;
    int rows = 0;
                                                                        // There is no point to eat more than can chew
    for (auto it = finalRequests.rbegin(); it != finalRequests.rend() && size_t(rows) < m_rootItem.children.cacheSize; ++it) {
        qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "FINAL start=" << it->start << "end=" << it->end << "roles=" << it->roles;

        QRemoteObjectPendingReply<DataEntries> reply = replicaRowRequest(it->start, it->end, it->roles);
        RowWatcher *watcher = new RowWatcher(it->start, it->end, it->roles, reply);
        rows += 1 + it->end.first().row - it->start.first().row;
        m_pendingRequests.push_back(watcher);
        connect(watcher, &RowWatcher::finished, this, &QAbstractItemModelReplicaImplementation::requestedData);
    }
}

void QAbstractItemModelReplicaImplementation::onModelReset()
{
    if (!m_initDone)
        return;

    qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO;
    QRemoteObjectPendingCallWatcher *watcher = doModelReset();
    connect(watcher, &QRemoteObjectPendingCallWatcher::finished, this, &QAbstractItemModelReplicaImplementation::handleModelResetDone);
}

void QAbstractItemModelReplicaImplementation::onHeaderDataChanged(Qt::Orientation orientation, int first, int last)
{
    // TODO clean cache
    const int index = orientation == Qt::Horizontal ? 0 : 1;
    QVector<CacheEntry> &entries = m_headerData[index];
    for (int i = first; i < last; ++i )
        entries[i].data.clear();
    emit q->headerDataChanged(orientation, first, last);
}

void QAbstractItemModelReplicaImplementation::fetchPendingHeaderData()
{
    QVector<int> roles;
    QVector<int> sections;
    QVector<Qt::Orientation> orientations;
    for (const RequestedHeaderData &data : qAsConst(m_requestedHeaderData)) {
        roles.push_back(data.role);
        sections.push_back(data.section);
        orientations.push_back(data.orientation);
    }
    QRemoteObjectPendingReply<QVariantList> reply = replicaHeaderRequest(orientations, sections, roles);
    HeaderWatcher *watcher = new HeaderWatcher(orientations, sections, roles, reply);
    connect(watcher, &HeaderWatcher::finished, this, &QAbstractItemModelReplicaImplementation::requestedHeaderData);
    m_requestedHeaderData.clear();
    m_pendingRequests.push_back(watcher);
}

static inline QVector<QPair<int, int> > listRanges(const QVector<int> &list)
{
    QVector<QPair<int, int> > result;
    if (!list.isEmpty()) {
        QPair<int, int> currentElem = qMakePair(list.first(), list.first());
        QVector<int>::const_iterator end = list.end();
        for (QVector<int>::const_iterator it = list.constBegin() + 1; it != end; ++it) {
            if (currentElem.first == *it +1)
                currentElem.first = *it;
            else if ( currentElem.second == *it -1)
                currentElem.second = *it;
            else if (currentElem.first <= *it && currentElem.second >= *it)
                continue;
            else {
                result.push_back(currentElem);
                currentElem.first = *it;
                currentElem.second = *it;
            }
        }
        result.push_back(currentElem);
    }
    return result;
}

void QAbstractItemModelReplicaImplementation::requestedHeaderData(QRemoteObjectPendingCallWatcher *qobject)
{
    HeaderWatcher *watcher = static_cast<HeaderWatcher *>(qobject);
    Q_ASSERT(watcher);

    QVariantList data = watcher->returnValue().value<QVariantList>();
    Q_ASSERT(watcher->orientations.size() == data.size());
    Q_ASSERT(watcher->sections.size() == data.size());
    Q_ASSERT(watcher->roles.size() == data.size());
    QVector<int> horizontalSections;
    QVector<int> verticalSections;

    for (int i = 0; i < data.size(); ++i) {
        if (watcher->orientations[i] == Qt::Horizontal)
            horizontalSections.append(watcher->sections[i]);
        else
            verticalSections.append(watcher->sections[i]);
        const int index = watcher->orientations[i] == Qt::Horizontal ? 0 : 1;
        const int role = watcher->roles[i];
        QHash<int, QVariant> &dat = m_headerData[index][watcher->sections[i]].data;
        dat[role] = data[i];
    }
    QVector<QPair<int, int> > horRanges = listRanges(horizontalSections);
    QVector<QPair<int, int> > verRanges = listRanges(verticalSections);

    for (int i = 0; i < horRanges.size(); ++i)
        emit q->headerDataChanged(Qt::Horizontal, horRanges[i].first, horRanges[i].second);
    for (int i = 0; i < verRanges.size(); ++i)
        emit q->headerDataChanged(Qt::Vertical, verRanges[i].first, verRanges[i].second);
    m_pendingRequests.removeAll(watcher);
    delete watcher;
}

QAbstractItemModelReplica::QAbstractItemModelReplica(QAbstractItemModelReplicaImplementation *rep, QtRemoteObjects::InitialAction action, const QVector<int> &rolesHint)
    : QAbstractItemModel()
    , d(rep)
{
    d->m_initialAction = action;
    d->m_initialFetchRolesHint = rolesHint;

    rep->setModel(this);
    connect(rep, &QAbstractItemModelReplicaImplementation::initialized, d.data(), &QAbstractItemModelReplicaImplementation::init);
}

QAbstractItemModelReplica::~QAbstractItemModelReplica()
{
}

static QVariant findData(const CachedRowEntry &row, const QModelIndex &index, int role, bool *cached = 0)
{
    if (index.column() < row.size()) {
        const CacheEntry &entry = row[index.column()];
        QHash<int, QVariant>::ConstIterator it = entry.data.constFind(role);
        if (it != entry.data.constEnd()) {
            if (cached)
                *cached = true;
            return it.value();
        }
    }
    if (cached)
        *cached = false;
    return QVariant();
}

QItemSelectionModel* QAbstractItemModelReplica::selectionModel() const
{
    return d->m_selectionModel.data();
}

bool QAbstractItemModelReplica::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (role == Qt::UserRole - 1) {
        auto parent = d->cacheData(index);
        if (!parent)
            return false;
        bool ok = true;
        auto row = value.toInt(&ok);
        if (ok)
            parent->ensureChildren(row, row);
        return ok;
    }
    if (!index.isValid())
        return false;
    if (index.row() < 0 || index.row() >= rowCount(index.parent()))
        return false;
    if (index.column() < 0 || index.column() >= columnCount(index.parent()))
        return false;

    const QVector<int > &availRoles = availableRoles();
    const QVector<int>::const_iterator res = std::find(availRoles.begin(), availRoles.end(), role);
    if (res == availRoles.end()) {
        qCWarning(QT_REMOTEOBJECT_MODELS) << "Tried to setData for index" << index << "on a not supported role" << role;
        return false;
    }
    // sendInvocationRequest to change server side data;
    d->replicaSetData(toModelIndexList(index, this), value, role);
    return true;
}

QVariant QAbstractItemModelReplica::data(const QModelIndex & index, int role) const
{

    if (!d->isInitialized()) {
        qCDebug(QT_REMOTEOBJECT_MODELS)<<"Data not initialized yet";
        return QVariant();
    }

    if (!index.isValid())
        return QVariant();

    if (!availableRoles().contains(role))
        return QVariant();

    auto item = d->cacheData(index);
    if (item) {
        bool cached = false;
        QVariant result = findData(item->cachedRowEntry, index, role, &cached);
        if (cached)
            return result;
    }

    auto parentItem = d->cacheData(index.parent());
    Q_ASSERT(parentItem);
    Q_ASSERT(index.row() < parentItem->rowCount);
    const int row = index.row();
    IndexList parentList = toModelIndexList(index.parent(), this);
    IndexList start = IndexList() << parentList << ModelIndex(row, 0);
    IndexList end = IndexList() << parentList << ModelIndex(row, std::max(0, parentItem->columnCount - 1));
    Q_ASSERT(toQModelIndex(start, this).isValid());

    RequestedData data;
    QVector<int> roles;
    roles << role;
    data.start = start;
    data.end = end;
    data.roles = roles;
    d->m_requestedData.push_back(data);
    qCDebug(QT_REMOTEOBJECT_MODELS) << "FETCH PENDING DATA" << start << end << roles;
    QMetaObject::invokeMethod(d.data(), "fetchPendingData", Qt::QueuedConnection);
    return QVariant{};
}
QModelIndex QAbstractItemModelReplica::parent(const QModelIndex &index) const
{
    if (!index.isValid() || !index.internalPointer())
        return QModelIndex();
    auto parent = static_cast<CacheData*>(index.internalPointer());
    Q_ASSERT(parent);
    if (parent == &d->m_rootItem)
        return QModelIndex();
    if (d->m_activeParents.find(parent) == d->m_activeParents.end() || d->m_activeParents.find(parent->parent) == d->m_activeParents.end())
        return QModelIndex();
    int row = parent->parent->children.find(parent);
    Q_ASSERT(row >= 0);
    return createIndex(row, 0, parent->parent);
}
QModelIndex QAbstractItemModelReplica::index(int row, int column, const QModelIndex &parent) const
{
    auto parentItem = d->cacheData(parent);
    if (!parentItem)
        return QModelIndex();

    Q_ASSERT_X((parent.isValid() && parentItem && parentItem != &d->m_rootItem) || (!parent.isValid() && parentItem == &d->m_rootItem), __FUNCTION__, qPrintable(QString(QLatin1String("isValid=%1 equals=%2")).arg(parent.isValid()).arg(parentItem == &d->m_rootItem)));

    // hmpf, following works around a Q_ASSERT-bug in QAbstractItemView::setModel which does just call
    // d->model->index(0,0) without checking the range before-hand what triggers our assert in case the
    // model is empty when view::setModel is called :-/ So, work around with the following;
    if (row < 0 || row >= parentItem->rowCount)
        return QModelIndex();

    if (column < 0 || column >= parentItem->columnCount)
        return QModelIndex();

    if (parentItem != &d->m_rootItem)
        parentItem->ensureChildren(row, row);
    return createIndex(row, column, reinterpret_cast<void*>(parentItem));
}
bool QAbstractItemModelReplica::hasChildren(const QModelIndex &parent) const
{
    auto parentItem = d->cacheData(parent);
    if (parent.isValid() && parent.column() != 0)
        return false;
    else
        return parentItem ? parentItem->hasChildren : false;
}
int QAbstractItemModelReplica::rowCount(const QModelIndex &parent) const
{
    auto parentItem = d->cacheData(parent);
    const bool canHaveChildren = parentItem && parentItem->hasChildren && !parentItem->rowCount && parent.column() == 0;
    if (canHaveChildren) {
        IndexList parentList = toModelIndexList(parent, this);
        QRemoteObjectPendingReply<QSize> reply = d->replicaSizeRequest(parentList);
        SizeWatcher *watcher = new SizeWatcher(parentList, reply);
        connect(watcher, &SizeWatcher::finished, d.data(), &QAbstractItemModelReplicaImplementation::handleSizeDone);
    } else if (parent.column() > 0) {
        return 0;
    }

    return parentItem ? parentItem->rowCount : 0;
}
int QAbstractItemModelReplica::columnCount(const QModelIndex &parent) const
{
    if (parent.isValid() && parent.column() > 0)
        return 0;
    auto parentItem = d->cacheData(parent);
    if (!parentItem)
        return 0;
    while (parentItem->columnCount < 0 && parentItem->parent)
        parentItem = parentItem->parent;
    return std::max(0, parentItem->columnCount);
}

QVariant QAbstractItemModelReplica::headerData(int section, Qt::Orientation orientation, int role) const
{
    const int index = orientation == Qt::Horizontal ? 0 : 1;
    const QVector<CacheEntry> elem = d->m_headerData[index];
    if (section >= elem.size())
        return QVariant();

    const QHash<int, QVariant> &dat = elem.at(section).data;
    QHash<int, QVariant>::ConstIterator it = dat.constFind(role);
    if (it != dat.constEnd())
        return it.value();

    RequestedHeaderData data;
    data.role = role;
    data.section = section;
    data.orientation = orientation;
    d->m_requestedHeaderData.push_back(data);
    QMetaObject::invokeMethod(d.data(), "fetchPendingHeaderData", Qt::QueuedConnection);
    return QVariant();
}

Qt::ItemFlags QAbstractItemModelReplica::flags(const QModelIndex &index) const
{
    CacheEntry *entry = d->cacheEntry(index);
    return entry ? entry->flags : Qt::NoItemFlags;
}

bool QAbstractItemModelReplica::isInitialized() const
{
    return d->isInitialized();
}

bool QAbstractItemModelReplica::hasData(const QModelIndex &index, int role) const
{
    if (!d->isInitialized() || !index.isValid())
        return false;
    auto item = d->cacheData(index);
    if (!item)
        return false;
    bool cached = false;
    const CachedRowEntry &entry = item->cachedRowEntry;
    QVariant result = findData(entry, index, role, &cached);
    Q_UNUSED(result);
    return cached;
}

size_t QAbstractItemModelReplica::rootCacheSize() const
{
    return d->m_rootItem.children.cacheSize;
}

void QAbstractItemModelReplica::setRootCacheSize(size_t rootCacheSize)
{
    d->m_rootItem.children.setCacheSize(rootCacheSize);
}

QVector<int> QAbstractItemModelReplica::availableRoles() const
{
    return d->availableRoles();
}

QHash<int, QByteArray> QAbstractItemModelReplica::roleNames() const
{
    return d->roleNames();
}

QT_END_NAMESPACE
