//========================================================================
//
// Outline.cc
//
// Copyright 2002-2003 Glyph & Cog, LLC
//
//========================================================================

//========================================================================
//
// Modified under the Poppler project - http://poppler.freedesktop.org
//
// All changes made under the Poppler project to this file are licensed
// under GPL version 2 or later
//
// Copyright (C) 2005 Marco Pesenti Gritti <mpg@redhat.com>
// Copyright (C) 2008, 2016-2019, 2021, 2023 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2009 Nick Jones <nick.jones@network-box.com>
// Copyright (C) 2016 Jason Crain <jason@aquaticape.us>
// Copyright (C) 2017 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich
// Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
// Copyright (C) 2019, 2020 Oliver Sander <oliver.sander@tu-dresden.de>
// Copyright (C) 2021 RM <rm+git@arcsin.org>
// Copyright (C) 2024 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
//
//========================================================================

#include <config.h>

#include "goo/gmem.h"
#include "goo/GooString.h"
#include "PDFDoc.h"
#include "XRef.h"
#include "Link.h"
#include "PDFDocEncoding.h"
#include "Outline.h"
#include "UTF.h"

//------------------------------------------------------------------------

Outline::Outline(Object *outlineObjA, XRef *xrefA, PDFDoc *docA)
{
    outlineObj = outlineObjA;
    xref = xrefA;
    doc = docA;
    items = nullptr;
    if (!outlineObj->isDict()) {
        return;
    }
    const Object &first = outlineObj->dictLookupNF("First");
    items = OutlineItem::readItemList(nullptr, &first, xref, doc);
}

Outline::~Outline()
{
    if (items) {
        for (auto entry : *items) {
            delete entry;
        }
        delete items;
    }
}

static void insertChildHelper(const std::string &itemTitle, int destPageNum, unsigned int pos, Ref parentObjRef, PDFDoc *doc, XRef *xref, std::vector<OutlineItem *> &items)
{
    std::vector<OutlineItem *>::const_iterator it;
    if (pos >= items.size()) {
        it = items.end();
    } else {
        it = items.begin() + pos;
    }

    Array *a = new Array(xref);
    Ref *pageRef = doc->getCatalog()->getPageRef(destPageNum);
    if (pageRef != nullptr) {
        a->add(Object(*pageRef));
    } else {
        // if the page obj doesn't exist put the page number
        // PDF32000-2008 12.3.2.2 Para 2
        // as if it's a "Remote-Go-To Actions"
        // it's not strictly valid, but most viewers seem
        // to handle it without crashing
        // alternately, could put 0, or omit it
        a->add(Object(destPageNum - 1));
    }
    a->add(Object(objName, "Fit"));

    Object outlineItem = Object(new Dict(xref));

    GooString *g = new GooString(itemTitle);
    outlineItem.dictSet("Title", Object(g));
    outlineItem.dictSet("Dest", Object(a));
    outlineItem.dictSet("Count", Object(1));
    outlineItem.dictAdd("Parent", Object(parentObjRef));

    // add one to the main outline Object's count
    Object parentObj = xref->fetch(parentObjRef);
    int parentCount = parentObj.dictLookup("Count").getInt();
    parentObj.dictSet("Count", Object(parentCount + 1));
    xref->setModifiedObject(&parentObj, parentObjRef);

    Object prevItemObject;
    Object nextItemObject;

    Ref outlineItemRef = xref->addIndirectObject(outlineItem);

    // the next two statements fix up the parent object
    // for clarity we separate this out
    if (it == items.begin()) {
        // we will be the first item in the list
        // fix our parent
        parentObj.dictSet("First", Object(outlineItemRef));
    }
    if (it == items.end()) {
        // we will be the last item on the list
        // fix up our parent
        parentObj.dictSet("Last", Object(outlineItemRef));
    }

    if (it == items.end()) {
        if (!items.empty()) {
            // insert at the end, we handle this separately
            prevItemObject = xref->fetch((*(it - 1))->getRef());
            prevItemObject.dictSet("Next", Object(outlineItemRef));
            outlineItem.dictSet("Prev", Object((*(it - 1))->getRef()));
            xref->setModifiedObject(&prevItemObject, (*(it - 1))->getRef());
        }
    } else {
        nextItemObject = xref->fetch((*it)->getRef());
        nextItemObject.dictSet("Prev", Object(outlineItemRef));
        xref->setModifiedObject(&nextItemObject, (*it)->getRef());

        outlineItem.dictSet("Next", Object((*(it))->getRef()));

        if (it != items.begin()) {
            prevItemObject = xref->fetch((*(it - 1))->getRef());
            prevItemObject.dictSet("Next", Object(outlineItemRef));
            outlineItem.dictSet("Prev", Object((*(it - 1))->getRef()));
            xref->setModifiedObject(&prevItemObject, (*(it - 1))->getRef());
        }
    }

    OutlineItem *item = new OutlineItem(outlineItem.getDict(), outlineItemRef, nullptr, xref, doc);

    items.insert(it, item);
}

void Outline::insertChild(const std::string &itemTitle, int destPageNum, unsigned int pos)
{
    Ref outlineObjRef = xref->getCatalog().dictLookupNF("Outlines").getRef();
    insertChildHelper(itemTitle, destPageNum, pos, outlineObjRef, doc, xref, *items);
}

// ref is a valid reference to a list
// walk the list and free any children
// returns the number items deleted (just in case)
static int recursiveRemoveList(Ref ref, XRef *xref)
{
    int count = 0;
    bool done = false;

    Ref nextRef;
    Object tempObj;

    while (!done) {
        tempObj = xref->fetch(ref);

        if (!tempObj.isDict()) {
            // something horrible has happened
            break;
        }

        const Object &firstRef = tempObj.dictLookupNF("First");
        if (firstRef.isRef()) {
            count += recursiveRemoveList(firstRef.getRef(), xref);
        }

        const Object &nextObjRef = tempObj.dictLookupNF("Next");
        if (nextObjRef.isRef()) {
            nextRef = nextObjRef.getRef();
        } else {
            done = true;
        }
        xref->removeIndirectObject(ref);
        count++;
        ref = nextRef;
    }
    return count;
}

static void removeChildHelper(unsigned int pos, PDFDoc *doc, XRef *xref, std::vector<OutlineItem *> &items)
{
    std::vector<OutlineItem *>::const_iterator it;
    if (pos >= items.size()) {
        // position is out of range, do nothing
        return;
    } else {
        it = items.begin() + pos;
    }

    //  relink around this node
    Object itemObject = xref->fetch((*it)->getRef());
    Object parentObj = itemObject.dictLookup("Parent");
    Object prevItemObject = itemObject.dictLookup("Prev");
    Object nextItemObject = itemObject.dictLookup("Next");

    // delete 1 from the parent Count if it's positive
    Object countObj = parentObj.dictLookup("Count");
    int count = countObj.getInt();
    if (count > 0) {
        count--;
        parentObj.dictSet("Count", Object(count));
        xref->setModifiedObject(&parentObj, itemObject.dictLookupNF("Parent").getRef());
    }

    if (!prevItemObject.isNull() && !nextItemObject.isNull()) {
        // deletion is in the middle
        prevItemObject.dictSet("Next", Object((*(it + 1))->getRef()));
        xref->setModifiedObject(&prevItemObject, (*(it - 1))->getRef());

        nextItemObject.dictSet("Prev", Object((*(it - 1))->getRef()));
        xref->setModifiedObject(&nextItemObject, (*(it + 1))->getRef());
    } else if (prevItemObject.isNull() && nextItemObject.isNull()) {
        // deletion is only child
        parentObj.dictRemove("First");
        parentObj.dictRemove("Last");
        xref->setModifiedObject(&parentObj, itemObject.dictLookupNF("Parent").getRef());
    } else if (prevItemObject.isNull()) {
        // deletion at the front
        parentObj.dictSet("First", Object((*(it + 1))->getRef()));
        xref->setModifiedObject(&parentObj, itemObject.dictLookupNF("Parent").getRef());

        nextItemObject.dictRemove("Prev");
        xref->setModifiedObject(&nextItemObject, (*(it + 1))->getRef());
    } else {
        // deletion at the end
        parentObj.dictSet("Last", Object((*(it - 1))->getRef()));
        xref->setModifiedObject(&parentObj, itemObject.dictLookupNF("Parent").getRef());
        prevItemObject.dictRemove("Next");
        xref->setModifiedObject(&prevItemObject, (*(it - 1))->getRef());
    }

    // free any children
    const Object &firstRef = itemObject.dictLookupNF("First");
    if (firstRef.isRef()) {
        recursiveRemoveList(firstRef.getRef(), xref);
    }

    // free the pdf objects and the representation
    xref->removeIndirectObject((*it)->getRef());
    OutlineItem *oi = *it;
    items.erase(it);
    // deletion of the OutlineItem will delete all child
    // outline items in its destructor
    delete oi;
}

void Outline::removeChild(unsigned int pos)
{
    removeChildHelper(pos, doc, xref, *items);
}

//------------------------------------------------------------------------

int Outline::addOutlineTreeNodeList(const std::vector<OutlineTreeNode> &nodeList, Ref &parentRef, Ref &firstRef, Ref &lastRef)
{
    firstRef = Ref::INVALID();
    lastRef = Ref::INVALID();
    if (nodeList.empty()) {
        return 0;
    }

    int itemCount = 0;
    Ref prevNodeRef = Ref::INVALID();

    for (auto &node : nodeList) {

        Array *a = new Array(doc->getXRef());
        Ref *pageRef = doc->getCatalog()->getPageRef(node.destPageNum);
        if (pageRef != nullptr) {
            a->add(Object(*pageRef));
        } else {
            // if the page obj doesn't exist put the page number
            // PDF32000-2008 12.3.2.2 Para 2
            // as if it's a "Remote-Go-To Actions"
            // it's not strictly valid, but most viewers seem
            // to handle it without crashing
            // alternately, could put 0, or omit it
            a->add(Object(node.destPageNum - 1));
        }
        a->add(Object(objName, "Fit"));

        Object outlineItem = Object(new Dict(doc->getXRef()));
        Ref outlineItemRef = doc->getXRef()->addIndirectObject(outlineItem);

        if (firstRef == Ref::INVALID()) {
            firstRef = outlineItemRef;
        }
        lastRef = outlineItemRef;

        GooString *g = new GooString(node.title);
        outlineItem.dictSet("Title", Object(g));
        outlineItem.dictSet("Dest", Object(a));
        itemCount++;

        if (prevNodeRef != Ref::INVALID()) {
            outlineItem.dictSet("Prev", Object(prevNodeRef));

            // maybe easier way to fix up the previous object
            Object prevOutlineItem = xref->fetch(prevNodeRef);
            prevOutlineItem.dictSet("Next", Object(outlineItemRef));
            xref->setModifiedObject(&prevOutlineItem, prevNodeRef);
        }
        prevNodeRef = outlineItemRef;

        Ref firstChildRef;
        Ref lastChildRef;
        itemCount += addOutlineTreeNodeList(node.children, outlineItemRef, firstChildRef, lastChildRef);

        if (firstChildRef != Ref::INVALID()) {
            outlineItem.dictSet("First", Object(firstChildRef));
            outlineItem.dictSet("Last", Object(lastChildRef));
        }
        outlineItem.dictSet("Count", Object(itemCount));
        outlineItem.dictAdd("Parent", Object(parentRef));
    }
    return itemCount;
}

/* insert an outline into a PDF
   outline->setOutline({ {"page 1", 1,
                                         { { "1.1", 1, {} } }   },
                            {"page 2", 2, {} },
                            {"page 3", 3, {} },
                            {"page 4", 4,{ { "4.1", 4, {} },
                                           { "4.2", 4, {} },
                                         },
                            }
                       });
 */

void Outline::setOutline(const std::vector<OutlineTreeNode> &nodeList)
{
    // check if outlineObj is an object, if it's not make sure it exists
    if (!outlineObj->isDict()) {
        outlineObj = doc->getCatalog()->getCreateOutline();

        // make sure it was created
        if (!outlineObj->isDict()) {
            return;
        }
    }

    Ref outlineObjRef = xref->getCatalog().dictLookupNF("Outlines").getRef();
    Ref firstChildRef;
    Ref lastChildRef;

    // free any OutlineItem objects that will be replaced
    const Object &firstChildRefObj = outlineObj->dictLookupNF("First");
    if (firstChildRefObj.isRef()) {
        recursiveRemoveList(firstChildRefObj.getRef(), xref);
    }

    const int count = addOutlineTreeNodeList(nodeList, outlineObjRef, firstChildRef, lastChildRef);

    // modify the parent Outlines dict
    if (firstChildRef != Ref::INVALID()) {
        outlineObj->dictSet("First", Object(firstChildRef));
        outlineObj->dictSet("Last", Object(lastChildRef));
    } else {
        // nothing was inserted into the outline, so just remove the
        // child references in the top-level outline
        outlineObj->dictRemove("First");
        outlineObj->dictRemove("Last");
    }
    outlineObj->dictSet("Count", Object(count));
    xref->setModifiedObject(outlineObj, outlineObjRef);

    // reload the outline object from the xrefs

    if (items) {
        for (auto entry : *items) {
            delete entry;
        }
        delete items;
    }
    const Object &first = outlineObj->dictLookupNF("First");
    // we probably want to allow readItemList to create an empty list
    // but for now just check and do it ourselves here
    if (first.isRef()) {
        items = OutlineItem::readItemList(nullptr, &first, xref, doc);
    } else {
        items = new std::vector<OutlineItem *>();
    }
}

//------------------------------------------------------------------------

OutlineItem::OutlineItem(const Dict *dict, Ref refA, OutlineItem *parentA, XRef *xrefA, PDFDoc *docA)
{
    Object obj1;

    ref = refA;
    parent = parentA;
    xref = xrefA;
    doc = docA;
    kids = nullptr;

    obj1 = dict->lookup("Title");
    if (obj1.isString()) {
        const GooString *s = obj1.getString();
        title = TextStringToUCS4(s->toStr());
    }

    obj1 = dict->lookup("Dest");
    if (!obj1.isNull()) {
        action = LinkAction::parseDest(&obj1);
    } else {
        obj1 = dict->lookup("A");
        if (!obj1.isNull()) {
            action = LinkAction::parseAction(&obj1);
        }
    }

    startsOpen = false;
    obj1 = dict->lookup("Count");
    if (obj1.isInt()) {
        if (obj1.getInt() > 0) {
            startsOpen = true;
        }
    }
}

OutlineItem::~OutlineItem()
{
    if (kids) {
        for (auto entry : *kids) {
            delete entry;
        }
        delete kids;
        kids = nullptr;
    }
}

std::vector<OutlineItem *> *OutlineItem::readItemList(OutlineItem *parent, const Object *firstItemRef, XRef *xrefA, PDFDoc *docA)
{
    auto items = new std::vector<OutlineItem *>();

    // could be a hash (unordered_map) too for better avg case check
    // small number of objects expected, likely doesn't matter
    std::set<Ref> alreadyRead;

    OutlineItem *parentO = parent;
    while (parentO) {
        alreadyRead.insert(parentO->getRef());
        parentO = parentO->parent;
    }

    Object tempObj = firstItemRef->copy();
    while (tempObj.isRef() && (tempObj.getRefNum() >= 0) && (tempObj.getRefNum() < xrefA->getNumObjects()) && alreadyRead.find(tempObj.getRef()) == alreadyRead.end()) {
        Object obj = tempObj.fetch(xrefA);
        if (!obj.isDict()) {
            break;
        }
        alreadyRead.insert(tempObj.getRef());
        OutlineItem *item = new OutlineItem(obj.getDict(), tempObj.getRef(), parent, xrefA, docA);
        items->push_back(item);
        tempObj = obj.dictLookupNF("Next").copy();
    }
    return items;
}

void OutlineItem::open()
{
    if (!kids) {
        Object itemDict = xref->fetch(ref);
        if (itemDict.isDict()) {
            const Object &firstRef = itemDict.dictLookupNF("First");
            kids = readItemList(this, &firstRef, xref, doc);
        } else {
            kids = new std::vector<OutlineItem *>();
        }
    }
}

void OutlineItem::setTitle(const std::string &titleA)
{
    Object dict = xref->fetch(ref);
    GooString *g = new GooString(titleA);
    title = TextStringToUCS4(g->toStr());
    dict.dictSet("Title", Object(g));
    xref->setModifiedObject(&dict, ref);
}

bool OutlineItem::setPageDest(int i)
{
    Object dict = xref->fetch(ref);
    Object obj1;

    if (i < 1) {
        return false;
    }

    obj1 = dict.dictLookup("Dest");
    if (!obj1.isNull()) {
        int arrayLength = obj1.arrayGetLength();
        for (int index = 0; index < arrayLength; index++) {
            obj1.arrayRemove(0);
        }
        obj1.arrayAdd(Object(i - 1));
        obj1.arrayAdd(Object(objName, "Fit"));

        // unique_ptr will destroy previous on assignment
        action = LinkAction::parseDest(&obj1);
    } else {
        obj1 = dict.dictLookup("A");
        if (!obj1.isNull()) {
            // RM 20210505 Implement
        } else {
        }
        return false;
    }

    xref->setModifiedObject(&dict, ref);
    return true;
}

void OutlineItem::insertChild(const std::string &itemTitle, int destPageNum, unsigned int pos)
{
    open();
    insertChildHelper(itemTitle, destPageNum, pos, ref, doc, xref, *kids);
}

void OutlineItem::removeChild(unsigned int pos)
{
    open();
    removeChildHelper(pos, doc, xref, *kids);
}

void OutlineItem::setStartsOpen(bool value)
{
    startsOpen = value;
    Object dict = xref->fetch(ref);
    Object obj1 = dict.dictLookup("Count");
    if (obj1.isInt()) {
        const int count = obj1.getInt();
        if ((count > 0 && !value) || (count < 0 && value)) {
            // states requires change of sign
            dict.dictSet("Count", Object(-count));
            xref->setModifiedObject(&dict, ref);
        }
    }
}

bool OutlineItem::hasKids()
{
    open();
    return !kids->empty();
}

const std::vector<OutlineItem *> *OutlineItem::getKids()
{
    open();

    if (!kids || kids->empty()) {
        return nullptr;
    } else {
        return kids;
    }
}
