/* poppler-ps-converter.cc: qt interface to poppler
 * Copyright (C) 2007, 2009, 2010, 2015, 2020, 2022, Albert Astals Cid <aacid@kde.org>
 * Copyright (C) 2008, Pino Toscano <pino@kde.org>
 * Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
 * Copyright (C) 2011 Glad Deschrijver <glad.deschrijver@gmail.com>
 * Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
 * Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 * Copyright (C) 2014 Adrian Johnson <ajohnson@redneon.com>
 * Copyright (C) 2020 William Bader <williambader@hotmail.com>
 * Copyright (C) 2023 Kevin Ottens <kevin.ottens@enioka.com>. Work sponsored by De Bortoli Wines
 *
 * 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-qt5.h"

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

#include "PSOutputDev.h"

static void outputToQIODevice(void *stream, const char *data, size_t len)
{
    static_cast<QIODevice *>(stream)->write(data, len);
}

namespace Poppler {

class PSConverterPrivate : public BaseConverterPrivate
{
public:
    PSConverterPrivate();
    ~PSConverterPrivate() override;

    QList<int> pageList;
    QString title;
    double hDPI;
    double vDPI;
    int rotate;
    int paperWidth;
    int paperHeight;
    int marginRight;
    int marginBottom;
    int marginLeft;
    int marginTop;
    PSConverter::PSOptions opts;
    void (*pageConvertedCallback)(int page, void *payload);
    void *pageConvertedPayload;
};

PSConverterPrivate::PSConverterPrivate()
    : BaseConverterPrivate(),
      hDPI(72),
      vDPI(72),
      rotate(0),
      paperWidth(-1),
      paperHeight(-1),
      marginRight(0),
      marginBottom(0),
      marginLeft(0),
      marginTop(0),
      opts(PSConverter::Printing),
      pageConvertedCallback(nullptr),
      pageConvertedPayload(nullptr)
{
}

PSConverterPrivate::~PSConverterPrivate() = default;

PSConverter::PSConverter(DocumentData *document) : BaseConverter(*new PSConverterPrivate())
{
    Q_D(PSConverter);
    d->document = document;
}

PSConverter::~PSConverter() { }

void PSConverter::setPageList(const QList<int> &pageList)
{
    Q_D(PSConverter);
    d->pageList = pageList;
}

void PSConverter::setTitle(const QString &title)
{
    Q_D(PSConverter);
    d->title = title;
}

void PSConverter::setHDPI(double hDPI)
{
    Q_D(PSConverter);
    d->hDPI = hDPI;
}

void PSConverter::setVDPI(double vDPI)
{
    Q_D(PSConverter);
    d->vDPI = vDPI;
}

void PSConverter::setRotate(int rotate)
{
    Q_D(PSConverter);
    d->rotate = rotate;
}

void PSConverter::setPaperWidth(int paperWidth)
{
    Q_D(PSConverter);
    d->paperWidth = paperWidth;
}

void PSConverter::setPaperHeight(int paperHeight)
{
    Q_D(PSConverter);
    d->paperHeight = paperHeight;
}

void PSConverter::setRightMargin(int marginRight)
{
    Q_D(PSConverter);
    d->marginRight = marginRight;
}

void PSConverter::setBottomMargin(int marginBottom)
{
    Q_D(PSConverter);
    d->marginBottom = marginBottom;
}

void PSConverter::setLeftMargin(int marginLeft)
{
    Q_D(PSConverter);
    d->marginLeft = marginLeft;
}

void PSConverter::setTopMargin(int marginTop)
{
    Q_D(PSConverter);
    d->marginTop = marginTop;
}

void PSConverter::setStrictMargins(bool strictMargins)
{
    Q_D(PSConverter);
    if (strictMargins) {
        d->opts |= StrictMargins;
    } else {
        d->opts &= ~StrictMargins;
    }
}

void PSConverter::setForceOverprintPreview(bool forceOverprintPreview)
{
    Q_D(PSConverter);
    if (forceOverprintPreview) {
        d->opts |= ForceOverprintPreview;
    } else {
        d->opts &= ~ForceOverprintPreview;
    }
}

void PSConverter::setForceRasterize(bool forceRasterize)
{
    Q_D(PSConverter);
    if (forceRasterize) {
        d->opts |= ForceRasterization;
    } else {
        d->opts &= ~ForceRasterization;
    }
}

void PSConverter::setPSOptions(PSConverter::PSOptions options)
{
    Q_D(PSConverter);
    d->opts = options;
}

PSConverter::PSOptions PSConverter::psOptions() const
{
    Q_D(const PSConverter);
    return d->opts;
}

void PSConverter::setPageConvertedCallback(void (*callback)(int page, void *payload), void *payload)
{
    Q_D(PSConverter);
    d->pageConvertedCallback = callback;
    d->pageConvertedPayload = payload;
}

static bool annotDisplayDecideCbk(Annot *annot, void *user_data)
{
    if (annot->getType() == Annot::typeWidget) {
        return true; // Never hide forms
    } else {
        return *(bool *)user_data;
    }
}

bool PSConverter::convert()
{
    Q_D(PSConverter);
    d->lastError = NoError;

    Q_ASSERT(!d->pageList.isEmpty());
    Q_ASSERT(d->paperWidth != -1);
    Q_ASSERT(d->paperHeight != -1);

    if (d->document->locked) {
        d->lastError = FileLockedError;
        return false;
    }

    QIODevice *dev = d->openDevice();
    if (!dev) {
        d->lastError = OpenOutputError;
        return false;
    }

    QByteArray pstitle8Bit = d->title.toLocal8Bit();
    char *pstitlechar;
    if (!d->title.isEmpty()) {
        pstitlechar = pstitle8Bit.data();
    } else {
        pstitlechar = nullptr;
    }

    std::vector<int> pages;
    foreach (int page, d->pageList) {
        pages.push_back(page);
    }

    PSOutputDev *psOut = new PSOutputDev(outputToQIODevice, dev, pstitlechar, d->document->doc, pages, (d->opts & PrintToEPS) ? psModeEPS : psModePS, d->paperWidth, d->paperHeight, false, false, d->marginLeft, d->marginBottom,
                                         d->paperWidth - d->marginRight, d->paperHeight - d->marginTop, (d->opts & ForceRasterization) ? psAlwaysRasterize : psRasterizeWhenNeeded);
    if (d->opts & ForceOverprintPreview) {
        psOut->setForceRasterize(psAlwaysRasterize);
        psOut->setOverprintPreview(true);
    }

    if (d->opts & StrictMargins) {
        double xScale = ((double)d->paperWidth - (double)d->marginLeft - (double)d->marginRight) / (double)d->paperWidth;
        double yScale = ((double)d->paperHeight - (double)d->marginBottom - (double)d->marginTop) / (double)d->paperHeight;
        psOut->setScale(xScale, yScale);
    }

    if (psOut->isOk()) {
        bool isPrinting = (d->opts & Printing) ? true : false;
        bool showAnnotations = (d->opts & HideAnnotations) ? false : true;
        foreach (int page, d->pageList) {
            d->document->doc->displayPage(psOut, page, d->hDPI, d->vDPI, d->rotate, false, true, isPrinting, nullptr, nullptr, annotDisplayDecideCbk, &showAnnotations, true);
            if (d->pageConvertedCallback) {
                (*d->pageConvertedCallback)(page, d->pageConvertedPayload);
            }
        }
        delete psOut;
        d->closeDevice();
        return true;
    } else {
        delete psOut;
        d->closeDevice();
        return false;
    }
}

}
