/* poppler-document.cc: qt interface to poppler
 * Copyright (C) 2005, Net Integration Technologies, Inc.
 * Copyright (C) 2005, 2008, Brad Hards <bradh@frogmouth.net>
 * Copyright (C) 2005-2010, 2012, 2013, 2015, 2017-2019, Albert Astals Cid <aacid@kde.org>
 * Copyright (C) 2006-2010, Pino Toscano <pino@kde.org>
 * Copyright (C) 2010, 2011 Hib Eris <hib@hiberis.nl>
 * Copyright (C) 2012 Koji Otani <sho@bbr.jp>
 * Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 * Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
 * Copyright (C) 2014, 2018 Adam Reichold <adam.reichold@t-online.de>
 * Copyright (C) 2015 William Bader <williambader@hotmail.com>
 * Copyright (C) 2016 Jakub Alba <jakubalba@gmail.com>
 * Copyright (C) 2017 Adrian Johnson <ajohnson@redneon.com>
 * Copyright (C) 2017 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
 * 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
 *
 * 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 <config.h>
#include <ErrorCodes.h>
#include <GlobalParams.h>
#include <Outline.h>
#include <PDFDoc.h>
#include <Stream.h>
#include <Catalog.h>
#include <ViewerPreferences.h>
#include <DateInfo.h>
#include <GfxState.h>

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

#include "poppler-private.h"
#include "poppler-page-private.h"
#include "poppler-outline-private.h"

#if defined(USE_CMS)
#include <lcms2.h>
#endif

namespace Poppler {

  int DocumentData::count = 0;
  QMutex DocumentData::mutex;

  Document *Document::load(const QString &filePath, const QByteArray &ownerPassword,
			   const QByteArray &userPassword)
    {
	DocumentData *doc = new DocumentData(filePath, 
					     new GooString(ownerPassword.data()),
					     new GooString(userPassword.data()));
	return DocumentData::checkDocument(doc);
    }

    Document *Document::loadFromData(const QByteArray &fileContents,
			      const QByteArray &ownerPassword,
			      const QByteArray &userPassword)
    {
	// create stream
	DocumentData *doc = new DocumentData(fileContents,
					     new GooString(ownerPassword.data()),
					     new GooString(userPassword.data()));
	return DocumentData::checkDocument(doc);
    }
    
    Document *DocumentData::checkDocument(DocumentData *doc)
    {
	Document *pdoc;
	if (doc->doc->isOk() || doc->doc->getErrorCode() == errEncrypted) {
		pdoc = new Document(doc);
		if (doc->doc->getErrorCode() == errEncrypted)
			pdoc->m_doc->locked = true;
		else
		{
			pdoc->m_doc->locked = false;
			pdoc->m_doc->fillMembers();
		}
		return pdoc;
	}
	else
	{
		delete doc;
	}
	return nullptr;
    }

    Document::Document(DocumentData *dataA)
    {
	m_doc = dataA;
    }

    Document::~Document()
    {
	delete m_doc;
    }

    Page *Document::page(int index) const
    {
	Page *page = new Page(m_doc, index);
	if (page->m_page->page == nullptr) {
	  delete page;
	  return nullptr;
	}

	return page;
    }

    bool Document::isLocked() const
    {
	return m_doc->locked;
    }

    bool Document::unlock(const QByteArray &ownerPassword,
			  const QByteArray &userPassword)
    {
	if (m_doc->locked) {
	    /* racier then it needs to be */
	    DocumentData *doc2;
	    if (!m_doc->fileContents.isEmpty())
	    {
		doc2 = new DocumentData(m_doc->fileContents,
					new GooString(ownerPassword.data()),
					new GooString(userPassword.data()));
	    }
	    else
	    {
		doc2 = new DocumentData(m_doc->m_filePath,
					new GooString(ownerPassword.data()),
					new GooString(userPassword.data()));
	    }
	    if (!doc2->doc->isOk()) {
		delete doc2;
	    } else {
		delete m_doc;
		m_doc = doc2;
		m_doc->locked = false;
		m_doc->fillMembers();
	    }
	}
	return m_doc->locked;
    }

    Document::PageMode Document::pageMode() const
    {
	switch (m_doc->doc->getCatalog()->getPageMode()) {
	case Catalog::pageModeNone:
	    return UseNone;
	case Catalog::pageModeOutlines:
	    return UseOutlines;
	case Catalog::pageModeThumbs:
	    return UseThumbs;
	case Catalog::pageModeFullScreen:
	    return FullScreen;
	case Catalog::pageModeOC:
	    return UseOC;
	case Catalog::pageModeAttach:
	    return UseAttach;
	default:
	    return UseNone;
	}
    }

    Document::PageLayout Document::pageLayout() const
    {
	switch (m_doc->doc->getCatalog()->getPageLayout()) {
	case Catalog::pageLayoutNone:
	    return NoLayout;
	case Catalog::pageLayoutSinglePage:
	    return SinglePage;
	case Catalog::pageLayoutOneColumn:
	    return OneColumn;
	case Catalog::pageLayoutTwoColumnLeft:
	    return TwoColumnLeft;
	case Catalog::pageLayoutTwoColumnRight:
	    return TwoColumnRight;
	case Catalog::pageLayoutTwoPageLeft:
	    return TwoPageLeft;
	case Catalog::pageLayoutTwoPageRight:
	    return TwoPageRight;
	default:
	    return NoLayout;
	}
    }

    Qt::LayoutDirection Document::textDirection() const
    {
        if (!m_doc->doc->getCatalog()->getViewerPreferences())
            return Qt::LayoutDirectionAuto;

        switch (m_doc->doc->getCatalog()->getViewerPreferences()->getDirection()) {
        case ViewerPreferences::directionL2R:
            return Qt::LeftToRight;
        case ViewerPreferences::directionR2L:
            return Qt::RightToLeft;
        default:
            return Qt::LayoutDirectionAuto;
        }
    }

    int Document::numPages() const
    {
	return m_doc->doc->getNumPages();
    }

    QList<FontInfo> Document::fonts() const
    {
	QList<FontInfo> ourList;
	FontIterator it( 0, m_doc );
	while ( it.hasNext() )
	{
		ourList += it.next();
	}
	return ourList;
    }

    QList<EmbeddedFile*> Document::embeddedFiles() const
    {
	return m_doc->m_embeddedFiles;
    }

    FontIterator* Document::newFontIterator( int startPage ) const
    {
	return new FontIterator( startPage, m_doc );
    }

    QByteArray Document::fontData(const FontInfo &fi) const
    {
	QByteArray result;
	if (fi.isEmbedded())
	{
		XRef *xref = m_doc->doc->getXRef()->copy();

		Object refObj(fi.m_data->embRef);
		Object strObj = refObj.fetch(xref);
		if (strObj.isStream())
		{
			int c;
			strObj.streamReset();
			while ((c = strObj.streamGetChar()) != EOF)
			{
				result.append((char)c);
			}
			strObj.streamClose();
		}
		delete xref;
	}
	return result;
    }

    QString Document::info( const QString & type ) const
    {
	if (m_doc->locked) {
	    return QString();
	}

	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoStringEntry(type.toLatin1().constData()));
	return UnicodeParsedString(goo.data());
    }

    bool Document::setInfo( const QString & key, const QString & val )
    {
	if (m_doc->locked) {
	    return false;
	}

	GooString *goo = QStringToUnicodeGooString(val);
	m_doc->doc->setDocInfoStringEntry(key.toLatin1().constData(), goo);
	return true;
    }

    QString Document::title() const
    {
	if (m_doc->locked) {
	    return QString();
	}

	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoTitle());
	return UnicodeParsedString(goo.data());
    }

    bool Document::setTitle( const QString & val )
    {
	if (m_doc->locked) {
	    return false;
	}

	m_doc->doc->setDocInfoTitle(QStringToUnicodeGooString(val));
	return true;
    }

    QString Document::author() const
    {
	if (m_doc->locked) {
	    return QString();
	}

	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoAuthor());
	return UnicodeParsedString(goo.data());
    }

    bool Document::setAuthor( const QString & val )
    {
	if (m_doc->locked) {
	    return false;
	}

	m_doc->doc->setDocInfoAuthor(QStringToUnicodeGooString(val));
	return true;
    }

    QString Document::subject() const
    {
	if (m_doc->locked) {
	    return QString();
	}

	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoSubject());
	return UnicodeParsedString(goo.data());
    }

    bool Document::setSubject( const QString & val )
    {
	if (m_doc->locked) {
	    return false;
	}

	m_doc->doc->setDocInfoSubject(QStringToUnicodeGooString(val));
	return true;
    }

    QString Document::keywords() const
    {
	if (m_doc->locked) {
	    return QString();
	}

	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoKeywords());
	return UnicodeParsedString(goo.data());
    }

    bool Document::setKeywords( const QString & val )
    {
	if (m_doc->locked) {
	    return false;
	}

	m_doc->doc->setDocInfoKeywords(QStringToUnicodeGooString(val));
	return true;
    }

    QString Document::creator() const
    {
	if (m_doc->locked) {
	    return QString();
	}

	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoCreator());
	return UnicodeParsedString(goo.data());
    }

    bool Document::setCreator( const QString & val )
    {
	if (m_doc->locked) {
	    return false;
	}

	m_doc->doc->setDocInfoCreator(QStringToUnicodeGooString(val));
	return true;
    }

    QString Document::producer() const
    {
	if (m_doc->locked) {
	    return QString();
	}

	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoProducer());
	return UnicodeParsedString(goo.data());
    }

    bool Document::setProducer( const QString & val )
    {
	if (m_doc->locked) {
	    return false;
	}

	m_doc->doc->setDocInfoProducer(QStringToUnicodeGooString(val));
	return true;
    }

    bool Document::removeInfo()
    {
	if (m_doc->locked) {
	    return false;
	}

	m_doc->doc->removeDocInfo();
	return true;
    }

    QStringList Document::infoKeys() const
    {
	QStringList keys;

	if ( m_doc->locked )
	    return QStringList();

	QScopedPointer<XRef> xref(m_doc->doc->getXRef()->copy());
	if (!xref)
		return QStringList();
	Object info = xref->getDocInfo();
	if ( !info.isDict() )
	    return QStringList();

	Dict *infoDict = info.getDict();
	// somehow iterate over keys in infoDict
	keys.reserve(infoDict->getLength());
	for( int i=0; i < infoDict->getLength(); ++i ) {
	    keys.append( QString::fromLatin1(infoDict->getKey(i)) );
	}

	return keys;
    }

    QDateTime Document::date( const QString & type ) const
    {
	if (m_doc->locked) {
	    return QDateTime();
	}

	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoStringEntry(type.toLatin1().constData()));
	QString str = UnicodeParsedString(goo.data());
	return Poppler::convertDate(str.toLatin1().constData());
    }

    bool Document::setDate( const QString & key, const QDateTime & val )
    {
	if (m_doc->locked) {
	    return false;
	}

	m_doc->doc->setDocInfoStringEntry(key.toLatin1().constData(), QDateTimeToUnicodeGooString(val));
	return true;
    }

    QDateTime Document::creationDate() const
    {
	if (m_doc->locked) {
	    return QDateTime();
	}

	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoCreatDate());
	QString str = UnicodeParsedString(goo.data());
	return Poppler::convertDate(str.toLatin1().constData());
    }

    bool Document::setCreationDate( const QDateTime & val )
    {
	if (m_doc->locked) {
	    return false;
	}

	m_doc->doc->setDocInfoCreatDate(QDateTimeToUnicodeGooString(val));
	return true;
    }

    QDateTime Document::modificationDate() const
    {
	if (m_doc->locked) {
	    return QDateTime();
	}

	QScopedPointer<GooString> goo(m_doc->doc->getDocInfoModDate());
	QString str = UnicodeParsedString(goo.data());
	return Poppler::convertDate(str.toLatin1().constData());
    }

    bool Document::setModificationDate( const QDateTime & val )
    {
	if (m_doc->locked) {
	    return false;
	}

	m_doc->doc->setDocInfoModDate(QDateTimeToUnicodeGooString(val));
	return true;
    }

    bool Document::isEncrypted() const
    {
	return m_doc->doc->isEncrypted();
    }

    bool Document::isLinearized() const
    {
	return m_doc->doc->isLinearized();
    }

    bool Document::okToPrint() const
    {
	return m_doc->doc->okToPrint();
    }

    bool Document::okToPrintHighRes() const
    {
	return m_doc->doc->okToPrintHighRes();
    }

    bool Document::okToChange() const
    {
	return m_doc->doc->okToChange();
    }

    bool Document::okToCopy() const
    {
	return m_doc->doc->okToCopy();
    }

    bool Document::okToAddNotes() const
    {
	return m_doc->doc->okToAddNotes();
    }

    bool Document::okToFillForm() const
    {
	return m_doc->doc->okToFillForm();
    }

    bool Document::okToCreateFormFields() const
    {
	return ( okToFillForm() && okToChange() );
    }

    bool Document::okToExtractForAccessibility() const
    {
	return m_doc->doc->okToAccessibility();
    }

    bool Document::okToAssemble() const
    {
	return m_doc->doc->okToAssemble();
    }

    void Document::getPdfVersion(int *major, int *minor) const
    {
	if (major)
	    *major = m_doc->doc->getPDFMajorVersion();
	if (minor)
	    *minor = m_doc->doc->getPDFMinorVersion();
    }

    Page *Document::page(const QString &label) const
    {
	GooString label_g(label.toLatin1().data());
	int index;

	if (!m_doc->doc->getCatalog()->labelToIndex (&label_g, &index)) {
	    std::unique_ptr<GooString> label_ug(QStringToUnicodeGooString(label));
	    if (!m_doc->doc->getCatalog()->labelToIndex (label_ug.get(), &index)) {
	        return nullptr;
	    }
	}

	return page(index);
    }

    bool Document::hasEmbeddedFiles() const
    {
	return (!(0 == m_doc->doc->getCatalog()->numEmbeddedFiles()));
    }
    
    QDomDocument *Document::toc() const
    {
        Outline * outline = m_doc->doc->getOutline();
        if ( !outline )
            return nullptr;

        const GooList<OutlineItem*> * items = outline->getItems();
        if ( !items || items->size() < 1 )
            return nullptr;

        QDomDocument *toc = new QDomDocument();
        if ( items->size() > 0 )
           m_doc->addTocChildren( toc, toc, items );

        return toc;
    }

    QVector<OutlineItem> Document::outline() const
    {
      QVector<OutlineItem> result;

      if (::Outline *outline = m_doc->doc->getOutline()) {
	if (const GooList *items = outline->getItems()) {
	  for (void *item : *items) {
	    result.push_back(OutlineItem{new OutlineItemData{static_cast<::OutlineItem *>(item), m_doc}});
	  }
	}
      }

      return result;
    }

    LinkDestination *Document::linkDestination( const QString &name )
    {
        GooString * namedDest = QStringToGooString( name );
        LinkDestinationData ldd(nullptr, namedDest, m_doc, false);
        LinkDestination *ld = new LinkDestination(ldd);
        delete namedDest;
        return ld;
    }
    
    void Document::setPaperColor(const QColor &color)
    {
        m_doc->setPaperColor(color);
    }
    
    void Document::setColorDisplayProfile(void* outputProfileA)
    {
#if defined(USE_CMS)
        GfxColorSpace::setDisplayProfile((cmsHPROFILE)outputProfileA);
#else
        Q_UNUSED(outputProfileA);
#endif
    }

    void Document::setColorDisplayProfileName(const QString &name)
    {
#if defined(USE_CMS)
        GooString *profileName = QStringToGooString( name );
        GfxColorSpace::setDisplayProfileName(profileName);
        delete profileName;
#else
        Q_UNUSED(name);
#endif
    }

    void* Document::colorRgbProfile() const
    {
#if defined(USE_CMS)
        return (void*)GfxColorSpace::getRGBProfile();
#else
        return nullptr;
#endif
    }

    void* Document::colorDisplayProfile() const
    {
#if defined(USE_CMS)
       return (void*)GfxColorSpace::getDisplayProfile();
#else
       return nullptr;
#endif
    }

    QColor Document::paperColor() const
    {
    	return m_doc->paperColor;
    }

    void Document::setRenderBackend( Document::RenderBackend backend )
    {
        // no need to delete the outputdev as for the moment we always create a splash one
        // as the arthur one does not allow "precaching" due to it's signature
        // delete m_doc->m_outputDev;
        // m_doc->m_outputDev = NULL;
        m_doc->m_backend = backend;
    }

    Document::RenderBackend Document::renderBackend() const
    {
        return m_doc->m_backend;
    }

    QSet<Document::RenderBackend> Document::availableRenderBackends()
    {
        QSet<Document::RenderBackend> ret;
#if defined(HAVE_SPLASH)
        ret << Document::SplashBackend;
#endif
        ret << Document::ArthurBackend;
        return ret;
    }

    void Document::setRenderHint( Document::RenderHint hint, bool on )
    {
        const bool touchesOverprinting = hint & Document::OverprintPreview;
        
        int hintForOperation = hint;
        if (touchesOverprinting && !isOverprintPreviewAvailable())
            hintForOperation = hintForOperation & ~(int)Document::OverprintPreview;

        if ( on )
            m_doc->m_hints |= hintForOperation;
        else
            m_doc->m_hints &= ~hintForOperation;

    }

    Document::RenderHints Document::renderHints() const
    {
        return Document::RenderHints( m_doc->m_hints );
    }

    PSConverter *Document::psConverter() const
    {
        return new PSConverter(m_doc);
    }

    PDFConverter *Document::pdfConverter() const
    {
        return new PDFConverter(m_doc);
    }

    QString Document::metadata() const
    {
        QString result;
        Catalog *catalog = m_doc->doc->getCatalog();
        if (catalog && catalog->isOk())
        {
            GooString *s = catalog->readMetadata();
            if (s) result = UnicodeParsedString(s);
            delete s;
        }
        return result;
    }

    bool Document::hasOptionalContent() const
    {
        return ( m_doc->doc->getOptContentConfig() && m_doc->doc->getOptContentConfig()->hasOCGs() );
    }

    OptContentModel *Document::optionalContentModel()
    {
        if (m_doc->m_optContentModel.isNull()) {
	    m_doc->m_optContentModel = new OptContentModel(m_doc->doc->getOptContentConfig(), nullptr);
	}
        return (OptContentModel *)m_doc->m_optContentModel;
    }

    QStringList Document::scripts() const
    {
        Catalog *catalog = m_doc->doc->getCatalog();
        const int numScripts = catalog->numJS();
        QStringList scripts;
        for (int i = 0; i < numScripts; ++i) {
            GooString *s = catalog->getJS(i);
            if (s) {
                scripts.append(UnicodeParsedString(s));
                delete s;
            }
        }
        return scripts;
    }

    bool Document::getPdfId(QByteArray *permanentId, QByteArray *updateId) const
    {
        GooString gooPermanentId;
        GooString gooUpdateId;

        if (!m_doc->doc->getID(permanentId ? &gooPermanentId : nullptr, updateId ? &gooUpdateId : nullptr))
            return false;

        if (permanentId)
            *permanentId = gooPermanentId.c_str();
        if (updateId)
            *updateId = gooUpdateId.c_str();

        return true;
    }

    Document::FormType Document::formType() const
    {
        switch ( m_doc->doc->getCatalog()->getFormType() )
        {
            case Catalog::NoForm:
                return Document::NoForm;
            case Catalog::AcroForm:
                return Document::AcroForm;
            case Catalog::XfaForm:
                return Document::XfaForm;
        }

        return Document::NoForm; // make gcc happy
    }

    QVector<int> Document::formCalculateOrder() const
    {
        QVector<int> result;

        Form *form = m_doc->doc->getCatalog()->getForm();
        const std::vector<Ref> &calculateOrder = form->getCalculateOrder();
        for (uint i = 0; i < calculateOrder.size(); ++i) {
            FormWidget *w = form->findWidgetByRef(calculateOrder[i]);
            if (w) {
                result << w->getID();
            }
        }

        return result;
    }

    QDateTime convertDate( const char *dateString )
    {
        int year, mon, day, hour, min, sec, tzHours, tzMins;
        char tz;

        if ( parseDateString( dateString, &year, &mon, &day, &hour, &min, &sec, &tz, &tzHours, &tzMins ) )
        {
            QDate d( year, mon, day );
            QTime t( hour, min, sec );
            if ( d.isValid() && t.isValid() ) {
                QDateTime dt( d, t, Qt::UTC );
                if ( tz ) {
                    // then we have some form of timezone
                    if ( 'Z' == tz  ) {
                        // We are already at UTC
                    } else if ( '+' == tz ) {
                        // local time is ahead of UTC
                        dt = dt.addSecs(-1*((tzHours*60)+tzMins)*60);
                    } else if ( '-' == tz ) {
                        // local time is behind UTC
                        dt = dt.addSecs(((tzHours*60)+tzMins)*60);
                    } else {
                        qWarning("unexpected tz val");
                    }
                }
		return dt;
            }
        }
        return QDateTime();
    }

    QDateTime convertDate( char *dateString )
    {
        return convertDate( (const char *) dateString );
    }


    bool isCmsAvailable()
    {
#if defined(USE_CMS)
        return true;
#else
        return false;
#endif
    }

    bool isOverprintPreviewAvailable() {
#ifdef SPLASH_CMYK
        return true;
#else
        return false;
#endif
   }

}

