/*
 * Copyright (C) 2008, Pino Toscano <pino@kde.org>
 * Copyright (C) 2018, Adam Reichold <adam.reichold@t-online.de>
 * Copyright (C) 2019, Albert Astals Cid <aacid@kde.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "toc.h"

#include <poppler-qt5.h>

#include <QtGui/QStandardItemModel>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QTreeWidget>

#include <QDebug>

struct Node
{
    Node(Poppler::OutlineItem &&item, int row, Node *parent) : m_row(row), m_parent(parent), m_item(std::move(item)) { }

    ~Node() { qDeleteAll(m_children); }

    Node(const Node &) = delete;
    Node &operator=(const Node &) = delete;

    int m_row;
    Node *m_parent;
    Poppler::OutlineItem m_item;
    QVector<Node *> m_children;
};

class TocModel : public QAbstractItemModel
{
    Q_OBJECT
public:
    TocModel(QVector<Poppler::OutlineItem> &&items, QObject *parent) : QAbstractItemModel(parent)
    {
        for (int i = 0; i < items.count(); ++i) {
            m_topItems << new Node(std::move(items[i]), i, nullptr);
        }
    }

    ~TocModel() override { qDeleteAll(m_topItems); }

    QVariant data(const QModelIndex &index, int role) const override
    {
        if (role != Qt::DisplayRole)
            return {};

        Node *n = static_cast<Node *>(index.internalPointer());
        return n->m_item.name();
    }

    QModelIndex index(int row, int column, const QModelIndex &parent) const override
    {
        Node *p = static_cast<Node *>(parent.internalPointer());
        const QVector<Node *> &children = p ? p->m_children : m_topItems;

        return createIndex(row, column, children[row]);
    }

    QModelIndex parent(const QModelIndex &child) const override
    {
        Node *n = static_cast<Node *>(child.internalPointer());
        if (n->m_parent == nullptr)
            return QModelIndex();
        else
            return createIndex(n->m_parent->m_row, 0, n->m_parent);
    }

    int rowCount(const QModelIndex &parent) const override
    {
        Node *n = static_cast<Node *>(parent.internalPointer());
        if (!n) {
            return m_topItems.count();
        }

        if (n->m_children.isEmpty() && !n->m_item.isNull()) {
            QVector<Poppler::OutlineItem> items = n->m_item.children();
            for (int i = 0; i < items.count(); ++i) {
                n->m_children << new Node(std::move(items[i]), i, n);
            }
        }

        return n->m_children.count();
    }

    bool hasChildren(const QModelIndex &parent) const override
    {
        Node *n = static_cast<Node *>(parent.internalPointer());
        if (!n)
            return true;

        return n->m_item.hasChildren();
    }

    int columnCount(const QModelIndex &parent) const override { return 1; }

private:
    QVector<Node *> m_topItems;
};

TocDock::TocDock(QWidget *parent) : AbstractInfoDock(parent)
{
    m_tree = new QTreeView(this);
    setWidget(m_tree);
    m_tree->setAlternatingRowColors(true);
    m_tree->header()->hide();
    setWindowTitle(tr("TOC"));
    m_tree->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
}

TocDock::~TocDock() { }

void TocDock::expandItemModels(const QModelIndex &parent)
{
    TocModel *model = static_cast<TocModel *>(m_tree->model());
    for (int i = 0; i < model->rowCount(parent); ++i) {
        QModelIndex index = model->index(i, 0, parent);
        Node *n = static_cast<Node *>(index.internalPointer());
        if (n->m_item.isOpen()) {
            m_tree->setExpanded(index, true);
            expandItemModels(index);
        }
    }
}

void TocDock::fillInfo()
{
    auto outline = document()->outline();
    if (!outline.isEmpty()) {
        TocModel *model = new TocModel(std::move(outline), this);
        m_tree->setModel(model);

        expandItemModels(QModelIndex());
    } else {
        QStandardItemModel *model = new QStandardItemModel(this);
        QStandardItem *item = new QStandardItem(tr("No TOC"));
        item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
        model->appendRow(item);
        m_tree->setModel(model);
    }
}

void TocDock::documentClosed()
{
    m_tree->setModel(nullptr);
    AbstractInfoDock::documentClosed();
}

#include "toc.moc"
