/*
 * Copyright (C) 2009-2010, Pino Toscano <pino@kde.org>
 * Copyright (C) 2018, 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 "poppler-toc.h"

#include "poppler-toc-private.h"
#include "poppler-private.h"

#include "GooList.h"
#include "Outline.h"

using namespace poppler;

toc_private::toc_private()
{
}

toc_private::~toc_private()
{
}

toc* toc_private::load_from_outline(Outline *outline)
{
    if (!outline) {
        return nullptr;
    }

    const GooList *items = outline->getItems();
    if (!items || items->getLength() < 1) {
        return nullptr;
    }

    toc *newtoc = new toc();
    newtoc->d->root.d->is_open = true;
    newtoc->d->root.d->load_children(items);

    return newtoc;
}

toc_item_private::toc_item_private()
    : is_open(false)
{
}

toc_item_private::~toc_item_private()
{
    delete_all(children);
}

void toc_item_private::load(const OutlineItem *item)
{
    const Unicode *title_unicode = item->getTitle();
    const int title_length = item->getTitleLength();
    title = detail::unicode_to_ustring(title_unicode, title_length);
    is_open = item->isOpen();
}

void toc_item_private::load_children(const GooList *items)
{
    const int num_items = items->getLength();
    children.resize(num_items);
    for (int i = 0; i < num_items; ++i) {
        OutlineItem *item = (OutlineItem *)items->get(i);

        toc_item *new_item = new toc_item();
        new_item->d->load(item);
        children[i] = new_item;

        item->open();
        const GooList *item_children = item->getKids();
        if (item_children) {
            new_item->d->load_children(item_children);
        }
    }
}

/**
 \class poppler::toc poppler-toc.h "poppler/cpp/poppler-toc.h"

 Represents the TOC (Table of Contents) of a PDF %document.

 The TOC of a PDF %document is represented as a tree of items.
 */


toc::toc()
    : d(new toc_private())
{
}

/**
 Destroys the TOC.
 */
toc::~toc()
{
    delete d;
}

/**
 Returns the "invisible item" representing the root of the TOC.

 This item is special, it has no title nor actions, it is open and its children
 are the effective root items of the TOC. This is provided as a convenience
 when iterating through the TOC.

 \returns the root "item"
 */
toc_item* toc::root() const
{
    return &d->root;
}

/**
 \class poppler::toc_item poppler-toc.h "poppler/cpp/poppler-toc.h"

 Represents an item of the TOC (Table of Contents) of a PDF %document.
 */

/**
 \typedef std::vector<toc_item *>::const_iterator poppler::toc_item::iterator

 An iterator for the children of a TOC item.
 */


toc_item::toc_item()
    : d(new toc_item_private())
{
}

/**
 Destroys the TOC item.
 */
toc_item::~toc_item()
{
    delete d;
}

/**
 \returns the title of the TOC item
 */
ustring toc_item::title() const
{
    return d->title;
}

/**
 Returns whether the TOC item should be represented as open when showing the
 TOC.

 This is not a functional behaviour, but a visualisation hint of the item.
 Regardless of this state, the item can be expanded and collapsed freely when
 represented in a TOC view of a PDF viewer.

 \returns whether the TOC item should be open
 */
bool toc_item::is_open() const
{
    return d->is_open;
}

/**
 \returns the children of the TOC item
 */
std::vector<toc_item *> toc_item::children() const
{
    return d->children;
}

/**
 \returns an iterator to the being of the list of children of the TOC item
 */
toc_item::iterator toc_item::children_begin() const
{
    return d->children.begin();
}

/**
 \returns an iterator to the end of the list of children of the TOC item
 */
toc_item::iterator toc_item::children_end() const
{
    return d->children.end();
}
