/*
 * Copyright (C) 2014-2024 CZ.NIC
 *
 * 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 3 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/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations including
 * the two.
 */

#pragma once

#include <QObject>

#include "src/datovka_shared/identifiers/account_id.h"

/* Forward class declarations. */
class AccountDb;
class MessageDbSet;
class TagDb;

/* Functionality is derived from https://wiki.qt.io/QThreads_general_usage . */

/*!
 * @brief Encapsulates the back-up function to be run in a separate thread.
 */
class BackupWorker : public QObject {
	Q_OBJECT

public:
	/*!
	 * @brief Message database and their respective location.
	 */
	class MessageEntry {
	public:
		MessageEntry(MessageDbSet *s, const QString &d,
		    const QString &a, const QString &b, const AcntId &aId)
		    : dbSet(s), normSubdir(d), accountName(a), boxId(b),
		    acntId(aId)
		{}

		MessageDbSet *dbSet; /*!< Message database set. */
		QString normSubdir; /*!< Subdirectory where to store the content. */
		QString accountName; /*!< Account name. */
		QString boxId; /*!< Data box identifier. */
		AcntId acntId; /*!< Account identifier. */
	};

	/*!
	 * @brief Constructor.
	 */
	explicit BackupWorker(QObject *parent = Q_NULLPTR);

	/*!
	 * @brief Set backup directory.
	 *
	 * @param[in] normDir Directory where to store the back-up.
	 */
	void setDir(const QString &normDir);

	/*!
	 * @brief Set message entries.
	 *
	 * @param[in] msgDbs Message database sets.
	 * @return False on any error.
	 */
	bool setMessageDbSets(const QList<MessageEntry> &msgDbs);

	/*!
	 * @brief Set account database back-up file.
	 *
	 * @param[in] accountDbFile File where to store the account database.
	 */
	void setAccountDb(const QString &accountDbFile);

	/*!
	 * @brief Set tag database back-up file.
	 *
	 * @param[in] tagDbFile File where to store the tag database.
	 */
	void setTagDb(const QString &tagDbFile);

public slots:
	/*!
	 * @brief Main thread function.
	 */
	void process(void);

	/*!
	 * @brief Call this method to signalise that the loop should be aborted.
	 */
	void setBreakBackupLoop(void);

signals:
	/*!
	 * @brief Emitted when back-up is started.
	 *
	 * @param[in] min Minimal progress value.
	 * @param[in] max Maximal progress value.
	 */
	void started(int min, int max);

	/*!
	 * @brief Emitted during back-up.
	 *
	 * @param[in] val Progress value.
	 */
	void progress(int val);

	/*!
	 * @brief Emitted during back-up.
	 *
	 * @param[in] name Back-up task name.
	 */
	void working(const QString &name);

	/*!
	 * @brief Emitted on main thread exit.
	 */
	void finished(void);

	/*!
	 * @brief Emitted before exit when everything finished successfully.
	 */
	void succeeded(void);

	/*!
	 * @brief Emitted before exit when something failed.
	 */
	void failed(void);

	/*!
	 * @brief Emitted before exit when something failed.
	 *
	 * @param[in] title Error title.
	 * @param[in] text Error description.
	 */
	void warning(const QString &title, const QString &text);

private:
	QString m_normDir; /*!< Directory where to store the back-up hierarchy. */
	QList<MessageEntry> m_msgDbs; /*!< Where to store message databases. */
	QString m_accountDbFile; /*!< Where to store the account database. */
	QString m_tagDbFile; /*!< Where to store the tag database. */

	volatile bool m_breakBackupLoop; /*!< Setting to true interrupts back-up loop. */
};
