/***************************************************************************
 *   Copyright (C) 2008 by S. MANKOWSKI / G. DE BURE support@mankowski.fr  *
 *                                                                         *
 *   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 of the License, 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, see <http://www.gnu.org/licenses/>  *
 ***************************************************************************/
#ifndef SKGIMPORTEXPORTMANAGER_H
#define SKGIMPORTEXPORTMANAGER_H
/** @file
 * This file defines classes SKGImportExportManager.
 *
 * @author Stephane MANKOWSKI / Guillaume DE BURE
 */
#include <qobject.h>
#include <qstringlist.h>
#include <qmap.h>
#include <qurl.h>

#include "skgerror.h"
#include "skgbankmodeler_export.h"
#include "skgaccountobject.h"

class SKGDocumentBank;
class SKGAccountObject;
class SKGUnitObject;
class QDate;
class SKGImportPlugin;

/**
 *Manage import and export
 */
class SKGBANKMODELER_EXPORT SKGImportExportManager : public QObject
{
    Q_OBJECT
public:
    /**
     * Constructor.
     * @param iDocument the document
     * @param iFileName the file name
     */
    explicit SKGImportExportManager(SKGDocumentBank* iDocument,
                                    const QUrl& iFileName = QUrl(QStringLiteral("")));

    /**
     * Destructor
     */
    ~SKGImportExportManager() override;

    /**
     * Set the codec used for imports.
     * @param iCodec the codec name.
     */
    virtual inline void setCodec(const QString& iCodec)
    {
        m_codec = iCodec;
    }

    /**
     * Get the codec used for imports.
     * @return code.
     */
    virtual inline QString getCodec() const
    {
        return m_codec;
    }

    /**
     * Set the default account for import in case of account is not detected in imported file.
     * @param iAccount the account where to import. nullptr if you want to create a specific account for that.
     * @return an object managing the error.
     *   @see SKGError
     */
    virtual SKGError setDefaultAccount(SKGAccountObject* iAccount);

    /**
     * Set the default unit for import in case of unit is not detected in imported file.
     * @param iUnit the unit where to import. nullptr if you want to create a specific unit for that.
     * @return an object managing the error.
     *   @see SKGError
     */
    virtual SKGError setDefaultUnit(SKGUnitObject* iUnit);

    /**
     * Enable/disable the automatically validation of imported operations.
     * @param iValidation the mode.
     */
    virtual void setAutomaticValidation(bool iValidation);

    /**
     * get the automatic validation state
     * @return The automatic validation state.
     */
    virtual bool automaticValidation() const;

    /**
     * Enable/disable the automatically rules application on imported operations.
     * @param iApply the mode.
     */
    virtual void setAutomaticApplyRules(bool iApply);

    /**
    * get the automatic apply rules state
    * @return The automatic apply rules state.
    */
    virtual bool automaticApplyRules() const;

    /**
     * To authorize the import of operations after the last imported operation
     * @param iSinceLast the mode.
     */
    virtual void setSinceLastImportDate(bool iSinceLast);

    /**
    * get the since last import state
    * @return The since last import state.
    */
    virtual bool sinceLastImportDate() const;

    /**
     * Get parameters for Export
     * @return the parameters
     */
    virtual QMap<QString, QString> getExportParameters();

    /**
     * Set parameters for Export
     * @param iParameters the parameters
     */
    virtual void setExportParameters(const QMap<QString, QString>& iParameters);

    /**
     * Get parameters for Import
     * @return the parameters
     */
    virtual QMap<QString, QString> getImportParameters();

    /**
     * Set parameters for Import
     * @param iParameters the parameters
     */
    virtual void setImportParameters(const QMap<QString, QString>& iParameters);

    /**
     * Get the default value of a parameter
     * @param iParameter the parameter
     */
    static QString getParameterDefaultValue(const QString& iParameter);

    /**
     * Get the mime type filter for import
     * @param iIncludingAll to include the "All supported format"
     * @return the mime type filter
     */
    static QString getImportMimeTypeFilter(bool iIncludingAll = true);

    /**
     * Import the file in the document
     * @return an object managing the error.
     *   @see SKGError
     */
    virtual SKGError importFile();

    /**
     * Get the mime type filter for export
     * @param iIncludingAll to include the "All supported format"
     * @return the mime type filter
     */
    static QString getExportMimeTypeFilter(bool iIncludingAll = true);

    /**
     * Export the file in the document
     * @return an object managing the error.
     *   @see SKGError
     */
    virtual SKGError exportFile();

    /**
     * Anonymize the document.
     * This function must not be launched into a transaction
     * @return an object managing the error.
     *   @see SKGError
     */
    virtual SKGError anonymize();

    /**
     * Find and group operations
     * @param oNbOperationsMerged returns the number of operations merged.
     * @param iAdditionnalCondition a condition on operations to check (eg. A.t_imported='T' AND B.t_imported='T'")
     * @return an object managing the error.
     *   @see SKGError
     */
    virtual SKGError findAndGroupTransfers(int& oNbOperationsMerged, const QString& iAdditionnalCondition);

    /**
     * Find and group operations
     * @param oNbOperationsMerged returns the number of operations merged.
     * @param iOnCurrentlyImport to apply the grouping only on currently imported operations.
     * @return an object managing the error.
     *   @see SKGError
     */
    virtual SKGError findAndGroupTransfers(int& oNbOperationsMerged, bool iOnCurrentlyImport = false);

    /**
     * Clean operations after an import coming from bank's web sites
     * @return an object managing the error.
     *   @see SKGError
     */
    virtual SKGError cleanBankImport();

    /**
     * Get the document
     * @return the document.
     */
    virtual inline SKGDocumentBank* getDocument()
    {
        return m_document;
    }

    /**
     * Get the file name extension
     * @return the file name.
     */
    virtual QString getFileNameExtension() const;

    /**
     * Get the file name
     * @return the file name.
     */
    virtual QUrl getFileName() const;

    /**
     * Get the local file name
     * @param iDownload create the local file by downloading the file.
     * @return the local file name.
     */
    virtual QString getLocalFileName(bool iDownload = true);

    /**
     * Return the default account for import
     * @param oAccount the default account for import.
     * @return an object managing the error.
     *   @see SKGError
     */
    virtual SKGError getDefaultAccount(SKGAccountObject& oAccount);

    /**
     * Return the preferred unit for a date for import
     * @param oUnit the default unit for import.
     * @param iDate the date.
     * @brief
     * If @see setDefaultUnit is used then getDefaultUnit will return this unit.
     * else return the unit compatible with entry date and with a value nearest than 1
     * else a new unit is created and returned
     * @return an object managing the error.
     *   @see SKGError
     */
    virtual SKGError getDefaultUnit(SKGUnitObject& oUnit, const QDate* iDate = nullptr);

    /**
     * Finalize an import by changing state and applying rules
     *   @see SKGError
     */
    virtual SKGError finalizeImportation();

    /**
     * Add an account to check during finalization
     * @param iAccount the account.
     * @param iBalance the balance.
     */
    virtual void addAccountToCheck(const SKGAccountObject& iAccount, double iBalance);

    /**
     * get accounts to check
     * @return the accounts and balances to check.
     */
    virtual QList<QPair<SKGAccountObject, double>> getAccountsToCheck();

private:
    Q_DISABLE_COPY(SKGImportExportManager)


    SKGImportPlugin* getImportPlugin();
    SKGImportPlugin* getExportPlugin();

    SKGDocumentBank* m_document;
    QUrl m_fileName;
    QString m_localFileName;
    SKGAccountObject* m_defaultAccount;
    SKGUnitObject* m_defaultUnit;
    QString m_codec;
    bool m_automaticValidationOfImportedOperation;
    bool m_automaticApplyRulesOfImportedOperation;
    bool m_since_last_import;
    SKGImportPlugin* m_importPlugin;
    SKGImportPlugin* m_exportPlugin;

    QList<QPair<SKGAccountObject, double>> m_AccountToCheck;
};

#endif
