/*
 * 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"
