/* This file is part of the Calligra libraries
   Copyright (C) 2001 Werner Trobin <trobin@kde.org>
                 2002 Werner Trobin <trobin@kde.org>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This library 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
Library General Public License for more details.

You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB.  If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/

#ifndef KIS_IMPORT_EXPORT_FILTER_H
#define KIS_IMPORT_EXPORT_FILTER_H

#include <QObject>
#include <QMap>
#include <QPointer>
#include <QString>
#include <QSharedPointer>
#include <kis_properties_configuration.h>
#include <kis_types.h>

class KoUpdater;
class KisDocument;
class KisConfigWidget;

#include "kritaui_export.h"


/**
 * @brief The base class for import and export filters.
 *
 * Derive your filter class from this base class and implement
 * the @ref convert() method. Don't forget to specify the Q_OBJECT
 * macro in your class even if you don't use signals or slots.
 * This is needed as filters are created on the fly.
 * The m_chain member allows access to the @ref KisFilterChain
 * which invokes the filter to query for input/output.
 *
 * @note Take care: The m_chain pointer is invalid while the constructor
 * runs due to the implementation -- @em don't use it in the constructor.
 * After the constructor, when running the @ref convert() method it's
 * guaranteed to be valid, so no need to check against 0.
 *
 * @note If the code is compiled in debug mode, setting CALLIGRA_DEBUG_FILTERS
 * environment variable to any value disables deletion of temporary files while
 * importing/exporting. This is useful for testing purposes.
 *
 * @author Werner Trobin <trobin@kde.org>
 * @todo the class has no constructor and therefore cannot initialize its private class
 */
class KRITAUI_EXPORT KisImportExportFilter : public QObject
{
    Q_OBJECT

public:
    /**
     * This enum is used to signal the return state of your filter.
     * Return OK in @ref convert() in case everything worked as expected.
     * Feel free to add some more error conditions @em before the last item
     * if it's needed.
     */
    enum ConversionStatus { OK,
                            StupidError,
                            UsageError,
                            CreationError,
                            FileNotFound,
                            StorageCreationError,
                            BadMimeType,
                            BadConversionGraph,
                            EmbeddedDocError,
                            WrongFormat,
                            NotImplemented,
                            ParsingError,
                            InternalError,
                            UnexpectedEOF,
                            UnexpectedOpcode,
                            UserCancelled,
                            OutOfMemory,
                            PasswordProtected,
                            InvalidFormat,
                            FilterEntryNull,
                            NoDocumentCreated,
                            DownloadFailed,
                            FilterCreationError,
                            ProgressCancelled,
                            UnsupportedVersion,
                            JustInCaseSomeBrokenCompilerUsesLessThanAByte = 255
                          };

    ~KisImportExportFilter() override;

    /**
     * @brief setChain set the chain information on the filter. The chain information
     * lets the filter know what document it's working on. The filter will not delete
     * @param chain the actual filter chain
     */
    void setChain(KisFilterChainSP chain);

    /**
     * The filter chain calls this method to perform the actual conversion.
     * The passed mimetypes should be a pair of those you specified in your
     * .desktop file.
     * You @em have to implement this method to make the filter work.
     *
     * @param from The mimetype of the source file/document
     * @param to The mimetype of the destination file/document
     * @return The error status, see the @ref #ConversionStatus enum.
     *         KisImportExportFilter::OK means that everything is alright.
     */
    virtual ConversionStatus convert(const QByteArray& from, const QByteArray& to, KisPropertiesConfigurationSP configuration = 0) = 0;

    /**
     * Set the updater to which the filter will report progress.
     * Every emit of the sigProgress signal is reported to the updater.
     */
    void setUpdater(const QPointer<KoUpdater>& updater);

    /**
     * Get the text version of the status value
     */
    static QString conversionStatusString(ConversionStatus status);

    /**
     * @brief defaultConfiguration defines the default settings for the given import export filter
     * @param from The mimetype of the source file/document
     * @param to The mimetype of the destination file/document
     * @return a serializable KisPropertiesConfiguration object
     */
    virtual KisPropertiesConfigurationSP defaultConfiguration(const QByteArray& from = "", const QByteArray& to = "") const;

    /**
     * @brief lastSavedConfiguration return the last saved configuration for this filter
     * @param from The mimetype of the source file/document
     * @param to The mimetype of the destination file/document
     * @return a serializable KisPropertiesConfiguration object
     */
    virtual KisPropertiesConfigurationSP lastSavedConfiguration(const QByteArray &from = "", const QByteArray &to = "") const;

    /**
     * @brief createConfigurationWidget creates a widget that can be used to define the settings for a given import/export filter
     * @param parent the ownder of the widget; the caller is responsible for deleting
     * @param from The mimetype of the source file/document
     * @param to The mimetype of the destination file/document
     *
     * @return the widget
     */
    virtual KisConfigWidget *createConfigurationWidget(QWidget *parent, const QByteArray& from = "", const QByteArray& to = "") const;


Q_SIGNALS:
    /**
     * Emit this signal with a value in the range of 1...100 to have some
     * progress feedback for the user in the statusbar of the application.
     *
     * @param value The actual progress state. Should always remain in
     * the range 1..100.
     */
    void sigProgress(int value);

protected:
    /**
     * This is the constructor your filter has to call, obviously.
     */
    KisImportExportFilter(QObject *parent = 0);

    KisDocument *inputDocument() const;
    KisDocument *outputDocument() const;
    QString inputFile() const;
    QString outputFile() const;
    bool getBatchMode() const;

private:

    KisImportExportFilter(const KisImportExportFilter& rhs);
    KisImportExportFilter& operator=(const KisImportExportFilter& rhs);

    class Private;
    Private *const d;

private Q_SLOTS:
    void slotProgress(int value);
};

#endif
