/****************************************************************************
**
** Copyright (C) 2009 Stephen Kelly <steveire@gmail.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** 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 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** 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 "dynamictreemodel.h"

#include <QtCore/QHash>
#include <QtCore/QList>
#include <QtCore/QTimer>
#include <QtCore/QDebug>

DynamicTreeModel::DynamicTreeModel(QObject *parent) :
    QAbstractItemModel(parent),
    nextId(1)
{
}

QModelIndex DynamicTreeModel::index(int row, int column, const QModelIndex &parent) const
{
//   if (column != 0)
//     return QModelIndex();

    if (column < 0 || row < 0)
        return QModelIndex();

    QList<QList<qint64> > childIdColumns = m_childItems.value(parent.internalId());

    const qint64 grandParent = findParentId(parent.internalId());
    if (grandParent >= 0) {
        QList<QList<qint64> > parentTable = m_childItems.value(grandParent);
        if (parent.column() >= parentTable.size())
            qFatal("%s: parent.column() must be less than parentTable.size()", Q_FUNC_INFO);
        QList<qint64> parentSiblings = parentTable.at(parent.column());
        if (parent.row() >= parentSiblings.size())
            qFatal("%s: parent.row() must be less than parentSiblings.size()", Q_FUNC_INFO);
    }

    if (childIdColumns.size() == 0)
        return QModelIndex();

    if (column >= childIdColumns.size())
        return QModelIndex();

    QList<qint64> rowIds = childIdColumns.at(column);

    if (row >= rowIds.size())
        return QModelIndex();

    qint64 id = rowIds.at(row);

    return createIndex(row, column, reinterpret_cast<void *>(id));
}

qint64 DynamicTreeModel::findParentId(qint64 searchId) const
{
    if (searchId <= 0)
        return -1;

    for (auto i = m_childItems.cbegin(), end = m_childItems.cend(); i != end; ++i) {
        for (const auto &list : i.value()) {
            if (list.contains(searchId))
                return i.key();
        }
    }
    return -1;
}

QModelIndex DynamicTreeModel::parent(const QModelIndex &index) const
{
    if (!index.isValid())
        return QModelIndex();

    qint64 searchId = index.internalId();
    qint64 parentId = findParentId(searchId);
    // Will never happen for valid index, but what the hey...
    if (parentId <= 0)
        return QModelIndex();

    qint64 grandParentId = findParentId(parentId);
    if (grandParentId < 0)
        grandParentId = 0;

    int column = 0;
    QList<qint64> childList = m_childItems.value(grandParentId).at(column);

    int row = childList.indexOf(parentId);

    return createIndex(row, column, reinterpret_cast<void *>(parentId));
}

int DynamicTreeModel::rowCount(const QModelIndex &index) const
{
    QList<QList<qint64> > cols = m_childItems.value(index.internalId());

    if (cols.size() == 0)
        return 0;

    if (index.column() > 0)
        return 0;

    return cols.at(0).size();
}

int DynamicTreeModel::columnCount(const QModelIndex &index) const
{
//   Q_UNUSED(index);
    return m_childItems.value(index.internalId()).size();
}

QVariant DynamicTreeModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    if (Qt::DisplayRole == role)
        return m_items.value(index.internalId());
    return QVariant();
}

void DynamicTreeModel::clear()
{
    beginResetModel();
    m_items.clear();
    m_childItems.clear();
    nextId = 1;
    endResetModel();
}

ModelChangeCommand::ModelChangeCommand(DynamicTreeModel *model, QObject *parent) :
    QObject(parent),
    m_model(model),
    m_numCols(1),
    m_startRow(-1),
    m_endRow(-1)
{
}

QModelIndex ModelChangeCommand::findIndex(const QList<int> &rows) const
{
    const int col = 0;
    QModelIndex parent = QModelIndex();
    for (int row : rows) {
        parent = m_model->index(row, col, parent);
        if (!parent.isValid())
            qFatal("%s: parent must be valid", Q_FUNC_INFO);
    }
    return parent;
}

ModelInsertCommand::ModelInsertCommand(DynamicTreeModel *model, QObject *parent) :
    ModelChangeCommand(model, parent)
{
}

void ModelInsertCommand::doCommand()
{
    QModelIndex parent = findIndex(m_rowNumbers);
    m_model->beginInsertRows(parent, m_startRow, m_endRow);
    qint64 parentId = parent.internalId();
    for (int row = m_startRow; row <= m_endRow; row++) {
        for (int col = 0; col < m_numCols; col++) {
            if (m_model->m_childItems[parentId].size() <= col)
                m_model->m_childItems[parentId].append(QList<qint64>());
//       QString name = QUuid::createUuid().toString();
            qint64 id = m_model->newId();
            QString name = QString::number(id);

            m_model->m_items.insert(id, name);
            m_model->m_childItems[parentId][col].insert(row, id);
        }
    }
    m_model->endInsertRows();
}

ModelMoveCommand::ModelMoveCommand(DynamicTreeModel *model, QObject *parent) :
    ModelChangeCommand(model, parent)
{
}

bool ModelMoveCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd,
                                     const QModelIndex &destParent, int destRow)
{
    return m_model->beginMoveRows(srcParent, srcStart, srcEnd, destParent, destRow);
}

void ModelMoveCommand::doCommand()
{
    QModelIndex srcParent = findIndex(m_rowNumbers);
    QModelIndex destParent = findIndex(m_destRowNumbers);

    if (!emitPreSignal(srcParent, m_startRow, m_endRow, destParent, m_destRow))
        return;

    for (int column = 0; column < m_numCols; ++column) {
        QList<qint64> l = m_model->m_childItems.value(srcParent.internalId())[column].mid(
            m_startRow, m_endRow - m_startRow + 1);

        for (int i = m_startRow; i <= m_endRow; i++)
            m_model->m_childItems[srcParent.internalId()][column].removeAt(m_startRow);
        int d;
        if (m_destRow < m_startRow) {
            d = m_destRow;
        } else {
            if (srcParent == destParent)
                d = m_destRow - (m_endRow - m_startRow + 1);
            else
                d = m_destRow;
        }

        foreach (const qint64 id, l)
            m_model->m_childItems[destParent.internalId()][column].insert(d++, id);
    }

    emitPostSignal();
}

void ModelMoveCommand::emitPostSignal()
{
    m_model->endMoveRows();
}

ModelResetCommand::ModelResetCommand(DynamicTreeModel *model, QObject *parent) :
    ModelMoveCommand(model, parent)
{
}

ModelResetCommand::~ModelResetCommand()
{
}

bool ModelResetCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd,
                                      const QModelIndex &destParent, int destRow)
{
    Q_UNUSED(srcParent);
    Q_UNUSED(srcStart);
    Q_UNUSED(srcEnd);
    Q_UNUSED(destParent);
    Q_UNUSED(destRow);

    return true;
}

void ModelResetCommand::emitPostSignal()
{
    m_model->beginResetModel();
    m_model->endResetModel();
}

ModelResetCommandFixed::ModelResetCommandFixed(DynamicTreeModel *model, QObject *parent) :
    ModelMoveCommand(model, parent)
{
}

ModelResetCommandFixed::~ModelResetCommandFixed()
{
}

bool ModelResetCommandFixed::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd,
                                           const QModelIndex &destParent, int destRow)
{
    Q_UNUSED(srcParent);
    Q_UNUSED(srcStart);
    Q_UNUSED(srcEnd);
    Q_UNUSED(destParent);
    Q_UNUSED(destRow);

    m_model->beginResetModel();
    return true;
}

void ModelResetCommandFixed::emitPostSignal()
{
    m_model->endResetModel();
}

ModelChangeChildrenLayoutsCommand::ModelChangeChildrenLayoutsCommand(DynamicTreeModel *model,
                                                                     QObject *parent) :
    ModelChangeCommand(model, parent)
{
}

void ModelChangeChildrenLayoutsCommand::doCommand()
{
    const QPersistentModelIndex parent1 = findIndex(m_rowNumbers);
    const QPersistentModelIndex parent2 = findIndex(m_secondRowNumbers);

    QList<QPersistentModelIndex> parents;
    parents << parent1;
    parents << parent2;

    emit m_model->layoutAboutToBeChanged(parents);

    int rowSize1 = -1;
    int rowSize2 = -1;

    for (int column = 0; column < m_numCols; ++column) {
        {
            QList<qint64> &l = m_model->m_childItems[parent1.internalId()][column];
            rowSize1 = l.size();
            l.prepend(l.takeLast());
        }
        {
            QList<qint64> &l = m_model->m_childItems[parent2.internalId()][column];
            rowSize2 = l.size();
            l.append(l.takeFirst());
        }
    }

    // If we're changing one of the parent indexes, we need to ensure that we do that before
    // changing any children of that parent. The reason is that we're keeping parent1 and parent2
    // around as QPersistentModelIndex instances, and we query idx.parent() in the loop.
    QModelIndexList persistent = m_model->persistentIndexList();
    foreach (const QModelIndex &parent, parents) {
        int idx = persistent.indexOf(parent);
        if (idx != -1)
            persistent.move(idx, 0);
    }

    foreach (const QModelIndex &idx, persistent) {
        if (idx.parent() == parent1) {
            if (idx.row() == rowSize1 - 1) {
                m_model->changePersistentIndex(idx,
                                               m_model->createIndex(0, idx.column(),
                                                                    idx.internalPointer()));
            } else {
                m_model->changePersistentIndex(idx,
                                               m_model->createIndex(idx.row() + 1, idx.column(),
                                                                    idx.internalPointer()));
            }
        } else if (idx.parent() == parent2) {
            if (idx.row() == 0) {
                m_model->changePersistentIndex(idx,
                                               m_model->createIndex(rowSize2 - 1, idx.column(),
                                                                    idx.internalPointer()));
            } else {
                m_model->changePersistentIndex(idx,
                                               m_model->createIndex(idx.row() - 1, idx.column(),
                                                                    idx.internalPointer()));
            }
        }
    }

    emit m_model->layoutChanged(parents);
}
