/* poppler-private.cc: qt interface to poppler
 * Copyright (C) 2005, Net Integration Technologies, Inc.
 * Copyright (C) 2006, 2011, 2015, 2017-2020 by Albert Astals Cid <aacid@kde.org>
 * Copyright (C) 2008, 2010, 2011, 2014 by Pino Toscano <pino@kde.org>
 * Copyright (C) 2013 by Thomas Freitag <Thomas.Freitag@alfa.de>
 * Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
 * Copyright (C) 2016 Jakub Alba <jakubalba@gmail.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-2020 Adam Reichold <adam.reichold@t-online.de>
 * Copyright (C) 2019, 2020, 2024 Oliver Sander <oliver.sander@tu-dresden.de>
 * Copyright (C) 2019 João Netto <joaonetto901@gmail.com>
 * Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>
 * Copyright (C) 2021 Mahmoud Khalil <mahmoudkhalil11@gmail.com>
 * Copyright (C) 2023 Shivodit Gill <shivodit.gill@gmail.com>
 * Copyright (C) 2024 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk>
 * Inspired on code by
 * Copyright (C) 2004 by Albert Astals Cid <tsdgeos@terra.es>
 * Copyright (C) 2004 by Enrico Ros <eros.kde@email.it>
 *
 * 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-private.h"
#include "poppler-form.h"

#include <QtCore/QByteArray>
#include <QtCore/QDebug>
#include <QtCore/QVariant>

#include <Link.h>
#include <Outline.h>
#include <PDFDocEncoding.h>
#include <UnicodeMap.h>
#include <UTF.h>

#ifdef ANDROID
#    include <QtCore/QString>
#    include <QtCore/QDir>
#    include <QtCore/QFile>
#    include <QtCore/QFileInfo>
#    include <QtCore/QStandardPaths>
#    include <QtCore/QDirIterator>
#endif

namespace Poppler {

namespace Debug {

static void qDebugDebugFunction(const QString &message, const QVariant & /*closure*/)
{
    qDebug() << message;
}

PopplerDebugFunc debugFunction = qDebugDebugFunction;
QVariant debugClosure;

}

void setDebugErrorFunction(PopplerDebugFunc function, const QVariant &closure)
{
    Debug::debugFunction = function ? function : Debug::qDebugDebugFunction;
    Debug::debugClosure = closure;
}

void qt5ErrorFunction(ErrorCategory /*category*/, Goffset pos, const char *msg)
{
    QString emsg;

    if (pos >= 0) {
        emsg = QStringLiteral("Error (%1): ").arg(pos);
    } else {
        emsg = QStringLiteral("Error: ");
    }
    emsg += QString::fromLatin1(msg);
    (*Debug::debugFunction)(emsg, Debug::debugClosure);
}

QString unicodeToQString(const Unicode *u, int len)
{
    const UnicodeMap *utf8Map = globalParams->getUtf8Map();

    // ignore the last characters if they are 0x0
    while ((len > 0) && (u[len - 1] == 0)) {
        --len;
    }

    GooString convertedStr;
    for (int i = 0; i < len; ++i) {
        char buf[8];
        const int n = utf8Map->mapUnicode(u[i], buf, sizeof(buf));
        convertedStr.append(buf, n);
    }

    return QString::fromUtf8(convertedStr.c_str(), convertedStr.getLength());
}

QString unicodeToQString(const std::vector<Unicode> &u)
{
    return unicodeToQString(u.data(), u.size());
}

QString UnicodeParsedString(const GooString *s1)
{
    return (s1) ? UnicodeParsedString(s1->toStr()) : QString();
}

QString UnicodeParsedString(const std::string &s1)
{
    if (s1.empty()) {
        return QString();
    }

    if (hasUnicodeByteOrderMark(s1) || hasUnicodeByteOrderMarkLE(s1)) {
        return QString::fromUtf16(reinterpret_cast<const ushort *>(s1.c_str()), s1.size() / 2);
    } else {
        int stringLength;
        const char *cString = pdfDocEncodingToUTF16(s1, &stringLength);
        auto result = QString::fromUtf16(reinterpret_cast<const ushort *>(cString), stringLength / 2);
        delete[] cString;
        return result;
    }
}

GooString *QStringToUnicodeGooString(const QString &s)
{
    if (s.isEmpty()) {
        return new GooString();
    }
    int len = s.length() * 2 + 2;
    char *cstring = (char *)gmallocn(len, sizeof(char));
    cstring[0] = (char)0xfe;
    cstring[1] = (char)0xff;
    for (int i = 0; i < s.length(); ++i) {
        cstring[2 + i * 2] = s.at(i).row();
        cstring[3 + i * 2] = s.at(i).cell();
    }
    GooString *ret = new GooString(cstring, len);
    gfree(cstring);
    return ret;
}

GooString *QStringToGooString(const QString &s)
{
    int len = s.length();
    char *cstring = (char *)gmallocn(s.length(), sizeof(char));
    for (int i = 0; i < len; ++i) {
        cstring[i] = s.at(i).unicode();
    }
    GooString *ret = new GooString(cstring, len);
    gfree(cstring);
    return ret;
}

GooString *QDateTimeToUnicodeGooString(const QDateTime &dt)
{
    if (!dt.isValid()) {
        return nullptr;
    }

    return QStringToUnicodeGooString(dt.toUTC().toString(QStringLiteral("yyyyMMddhhmmss+00'00'")));
}

Annot::AdditionalActionsType toPopplerAdditionalActionType(Annotation::AdditionalActionType type)
{
    switch (type) {
    case Annotation::CursorEnteringAction:
        return Annot::actionCursorEntering;
    case Annotation::CursorLeavingAction:
        return Annot::actionCursorLeaving;
    case Annotation::MousePressedAction:
        return Annot::actionMousePressed;
    case Annotation::MouseReleasedAction:
        return Annot::actionMouseReleased;
    case Annotation::FocusInAction:
        return Annot::actionFocusIn;
    case Annotation::FocusOutAction:
        return Annot::actionFocusOut;
    case Annotation::PageOpeningAction:
        return Annot::actionPageOpening;
    case Annotation::PageClosingAction:
        return Annot::actionPageClosing;
    case Annotation::PageVisibleAction:
        return Annot::actionPageVisible;
    case Annotation::PageInvisibleAction:
        return Annot::actionPageInvisible;
    }

    return Annot::actionCursorEntering;
}

static void linkActionToTocItem(const ::LinkAction *a, DocumentData *doc, QDomElement *e)
{
    if (!a || !e) {
        return;
    }

    switch (a->getKind()) {
    case actionGoTo: {
        // page number is contained/referenced in a LinkGoTo
        const LinkGoTo *g = static_cast<const LinkGoTo *>(a);
        const LinkDest *destination = g->getDest();
        if (!destination && g->getNamedDest()) {
            // no 'destination' but an internal 'named reference'. we could
            // get the destination for the page now, but it's VERY time consuming,
            // so better storing the reference and provide the viewport on demand
            const GooString *s = g->getNamedDest();
            QChar *charArray = new QChar[s->getLength()];
            for (int i = 0; i < s->getLength(); ++i) {
                charArray[i] = QChar(s->c_str()[i]);
            }
            QString aux(charArray, s->getLength());
            e->setAttribute(QStringLiteral("DestinationName"), aux);
            delete[] charArray;
        } else if (destination && destination->isOk()) {
            LinkDestinationData ldd(destination, nullptr, doc, false);
            e->setAttribute(QStringLiteral("Destination"), LinkDestination(ldd).toString());
        }
        break;
    }
    case actionGoToR: {
        // page number is contained/referenced in a LinkGoToR
        const LinkGoToR *g = static_cast<const LinkGoToR *>(a);
        const LinkDest *destination = g->getDest();
        if (!destination && g->getNamedDest()) {
            // no 'destination' but an internal 'named reference'. we could
            // get the destination for the page now, but it's VERY time consuming,
            // so better storing the reference and provide the viewport on demand
            const GooString *s = g->getNamedDest();
            QChar *charArray = new QChar[s->getLength()];
            for (int i = 0; i < s->getLength(); ++i) {
                charArray[i] = QChar(s->c_str()[i]);
            }
            QString aux(charArray, s->getLength());
            e->setAttribute(QStringLiteral("DestinationName"), aux);
            delete[] charArray;
        } else if (destination && destination->isOk()) {
            LinkDestinationData ldd(destination, nullptr, doc, g->getFileName() != nullptr);
            e->setAttribute(QStringLiteral("Destination"), LinkDestination(ldd).toString());
        }
        e->setAttribute(QStringLiteral("ExternalFileName"), g->getFileName()->c_str());
        break;
    }
    case actionURI: {
        const LinkURI *u = static_cast<const LinkURI *>(a);
        e->setAttribute(QStringLiteral("DestinationURI"), u->getURI().c_str());
    }
    default:;
    }
}

DocumentData::~DocumentData()
{
    qDeleteAll(m_embeddedFiles);
    delete (OptContentModel *)m_optContentModel;
    delete doc;
}

void DocumentData::init()
{
    m_backend = Document::SplashBackend;
    paperColor = Qt::white;
    m_hints = 0;
    m_optContentModel = nullptr;
    xrefReconstructed = false;
    xrefReconstructedCallback = {};

#ifdef ANDROID
    // Copy fonts from android apk to the app's storage dir, and
    // set the font directory path
    QString assetsFontDir = QStringLiteral("assets:/share/fonts");
    QString fontsdir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/fonts");
    QDir fontPath = QDir(fontsdir);

    if (fontPath.mkpath(fontPath.absolutePath())) {
        GlobalParams::setFontDir(fontPath.absolutePath().toStdString());
        QDirIterator iterator(assetsFontDir, QDir::NoFilter, QDirIterator::Subdirectories);

        while (iterator.hasNext()) {
            iterator.next();
            QFileInfo fontFileInfo = iterator.fileInfo();
            QString fontFilePath = assetsFontDir + QStringLiteral("/") + fontFileInfo.fileName();
            QString destPath = fontPath.absolutePath() + QStringLiteral("/") + fontFileInfo.fileName();
            QFile::copy(fontFilePath, destPath);
        }
    } else {
        GlobalParams::setFontDir("");
    }
#endif
}

void DocumentData::addTocChildren(QDomDocument *docSyn, QDomNode *parent, const std::vector<::OutlineItem *> *items)
{
    for (::OutlineItem *outlineItem : *items) {
        // iterate over every object in 'items'

        // 1. create element using outlineItem's title as tagName
        QString name = unicodeToQString(outlineItem->getTitle());

        QDomElement item = docSyn->createElement(name);
        parent->appendChild(item);

        // 2. find the page the link refers to
        const ::LinkAction *a = outlineItem->getAction();
        linkActionToTocItem(a, this, &item);

        item.setAttribute(QStringLiteral("Open"), QVariant((bool)outlineItem->isOpen()).toString());

        // 3. recursively descend over children
        outlineItem->open();
        const std::vector<::OutlineItem *> *children = outlineItem->getKids();
        if (children) {
            addTocChildren(docSyn, &item, children);
        }
    }
}

void DocumentData::noitfyXRefReconstructed()
{
    if (!xrefReconstructed) {
        xrefReconstructed = true;
    }

    if (xrefReconstructedCallback) {
        xrefReconstructedCallback();
    }
}

FormWidget *FormFieldData::getFormWidget(const FormField *f)
{
    return f->m_formData->fm;
}

FormFieldIconData *FormFieldIconData::getData(const FormFieldIcon &f)
{
    return f.d_ptr;
}
}
