/* poppler-private.h: qt interface to poppler
 * Copyright (C) 2005, Net Integration Technologies, Inc.
 * Copyright (C) 2005, 2008, Brad Hards <bradh@frogmouth.net>
 * Copyright (C) 2006-2009, 2011, 2012, 2017, 2018 by Albert Astals Cid <aacid@kde.org>
 * Copyright (C) 2007-2009, 2011, 2014 by Pino Toscano <pino@kde.org>
 * Copyright (C) 2011 Andreas Hartmetz <ahartmetz@gmail.com>
 * Copyright (C) 2011 Hib Eris <hib@hiberis.nl>
 * Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 * Copyright (C) 2013 Anthony Granger <grangeranthony@gmail.com>
 * Copyright (C) 2014 Bogdan Cristea <cristeab@gmail.com>
 * Copyright (C) 2014 Aki Koskinen <freedesktop@akikoskinen.info>
 * Copyright (C) 2016 Jakub Alba <jakubalba@gmail.com>
 * Copyright (C) 2017 Christoph Cullmann <cullmann@kde.org>
 * 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 Oliver Sander <oliver.sander@tu-dresden.de>
 * 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.
 */

#ifndef _POPPLER_PRIVATE_H_
#define _POPPLER_PRIVATE_H_

#include <QtCore/QFile>
#include <QtCore/QMutex>
#include <QtCore/QPointer>
#include <QtCore/QVector>

#include <config.h>
#include <GfxState.h>
#include <GlobalParams.h>
#include <PDFDoc.h>
#include <FontInfo.h>
#include <OutputDev.h>
#include <Error.h>
#if defined(HAVE_SPLASH)
#include <SplashOutputDev.h>
#endif

#include "poppler-qt5.h"
#include "poppler-embeddedfile-private.h"

class LinkDest;
class FormWidget;
class OutlineItem;

namespace Poppler {

    /* borrowed from kpdf */
    POPPLER_QT5_EXPORT QString unicodeToQString(const Unicode* u, int len);

    POPPLER_QT5_EXPORT QString UnicodeParsedString(const GooString *s1);

    POPPLER_QT5_EXPORT GooString *QStringToUnicodeGooString(const QString &s);

    POPPLER_QT5_EXPORT GooString *QStringToGooString(const QString &s);

    GooString *QDateTimeToUnicodeGooString(const QDateTime &dt);

    void qt5ErrorFunction(int pos, char *msg, va_list args);

    Annot::AdditionalActionsType toPopplerAdditionalActionType(Annotation::AdditionalActionType type);

    class LinkDestinationData
    {
        public:
            LinkDestinationData( const LinkDest *l, const GooString *nd, Poppler::DocumentData *pdfdoc, bool external )
             : ld(l), namedDest(nd), doc(pdfdoc), externalDest(external)
            {
            }

            const LinkDest *ld;
            const GooString *namedDest;
            Poppler::DocumentData *doc;
            bool externalDest;
    };

    class DocumentData {
    public:
	DocumentData(const QString &filePath, GooString *ownerPassword, GooString *userPassword)
	    {
		init();
		m_filePath = filePath;	

#ifdef _WIN32
		doc = new PDFDoc((wchar_t *)filePath.utf16(), filePath.length(), ownerPassword, userPassword);
#else
		GooString *fileName = new GooString(QFile::encodeName(filePath).constData());
		doc = new PDFDoc(fileName, ownerPassword, userPassword);
#endif

		delete ownerPassword;
		delete userPassword;
	    }
	
	DocumentData(const QByteArray &data, GooString *ownerPassword, GooString *userPassword)
	    {
		fileContents = data;
		MemStream *str = new MemStream((char*)fileContents.data(), 0, fileContents.length(), Object(objNull));
		init();
		doc = new PDFDoc(str, ownerPassword, userPassword);
		delete ownerPassword;
		delete userPassword;
	    }
	
	void init();
	
	~DocumentData();

	DocumentData(const DocumentData &) = delete;
	DocumentData& operator=(const DocumentData &) = delete;
	
	void addTocChildren( QDomDocument * docSyn, QDomNode * parent, const std::vector<::OutlineItem*> * items );
	
	void setPaperColor(const QColor &color)
	{
		paperColor = color;
	}
	
	void fillMembers()
	{
		int numEmb = doc->getCatalog()->numEmbeddedFiles();
		if (!(0 == numEmb)) {
			// we have some embedded documents, build the list
			for (int yalv = 0; yalv < numEmb; ++yalv) {
				FileSpec *fs = doc->getCatalog()->embeddedFile(yalv);
				m_embeddedFiles.append(new EmbeddedFile(*new EmbeddedFileData(fs)));
			}
		}
	}
	
	static Document *checkDocument(DocumentData *doc);

	PDFDoc *doc;
	QString m_filePath;
	QByteArray fileContents;
	bool locked;
	Document::RenderBackend m_backend;
	QList<EmbeddedFile*> m_embeddedFiles;
	QPointer<OptContentModel> m_optContentModel;
	QColor paperColor;
	int m_hints;
	static int count;
	static QMutex mutex;
    };

    class FontInfoData
    {
	public:
		FontInfoData()
		{
			isEmbedded = false;
			isSubset = false;
			type = FontInfo::unknown;
		}
		
		FontInfoData( ::FontInfo* fi )
		{
			if (fi->getName()) fontName = fi->getName()->c_str();
			if (fi->getFile()) fontFile = fi->getFile()->c_str();
			isEmbedded = fi->getEmbedded();
			isSubset = fi->getSubset();
			type = (Poppler::FontInfo::Type)fi->getType();
			embRef = fi->getEmbRef();
		}

		FontInfoData( const FontInfoData &fid ) = default;
		FontInfoData& operator=(const FontInfoData &) = default;

		QString fontName;
		QString fontFile;
		bool isEmbedded : 1;
		bool isSubset : 1;
		FontInfo::Type type;
		Ref embRef;
    };

    class FontIteratorData
    {
	public:
		FontIteratorData( int startPage, DocumentData *dd )
		  : fontInfoScanner( dd->doc, startPage )
		  , totalPages( dd->doc->getNumPages() )
		  , currentPage( qMax( startPage, 0 ) - 1 )
		{
		}

		~FontIteratorData()
		{
		}

		FontInfoScanner fontInfoScanner;
		int totalPages;
		int currentPage;
    };

    class TextBoxData
    {
	public:
		TextBoxData()
		  : nextWord(nullptr), hasSpaceAfter(false)
		{
		}

		QString text;
		QRectF bBox;
		TextBox *nextWord;
		QVector<QRectF> charBBoxes; // the boundingRect of each character
		bool hasSpaceAfter;
    };

    class FormFieldData
    {
	public:
		FormFieldData(DocumentData *_doc, ::Page *p, ::FormWidget *w) :
		doc(_doc), page(p), fm(w)
		{
		}

		DocumentData *doc;
		::Page *page;
		::FormWidget *fm;
		QRectF box;
    };

}

#endif
