/*******************************************************************************
***  This file is part of Dux Rei Nummariae.                                 ***
***                                                                          ***
***  Copyright (C) 2017, 2018, 2019, 2020, 2021                              ***
***  John Schneiderman <Licensing _AT_ Schneiderman _DOT_ me>                ***
***                                                                          ***
***  This program is free software: you can redistribute it and/or modify it ***
***  under the terms of the GNU Affero 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 Affero General Public License for more details.             ***
***                                                                          ***
***  You should have received a copy of the GNU Affero General Public License***
***  along with this program. If not, see <http://www.gnu.org/licenses/>.    ***
*******************************************************************************/
#ifndef DRN_FILE_STORAGE_BUDGETFILE_H_
#define DRN_FILE_STORAGE_BUDGETFILE_H_

#include <QString>

#include <map>
#include <tuple>

#include "file-storage_export.h"


namespace drn
{
namespace accounting
{

class AccountCode;
class AccountNumber;
class GeneralLedger;

}
namespace banking
{

enum class SupportedAccountTypes;
struct BankMap;
class BankName;

}
namespace budgeting
{

class Budget;
class BudgetSource;

}
namespace foundation
{

template<typename, typename>
class TypeIndexMap;

}
namespace file_storage
{

/**
 * @brief The manager for interacting with a budget file.
 */
class DRN_FILE_STORAGE_EXPORT BudgetFile
{
	QString directoryPath_;
	QString name_;
	QString backUpExtension_;

public:
	/// The default extension used when backing-up a budget file, on systems like KDE this will show
	/// a nice back-up icon.
	static const QChar defaultBackUpExtension_;
	/// The extension used when backing-up a back-up to a budget file.
	static const QString oldBackUpExtension_;

	BudgetFile();
	/**
	 * @brief Initialises the entire object using the supplied values.
	 *
	 * @exception Error When the supplied file location is empty.
	 * @exception Error When the supplied file location is not absolute.
	 * @exception Error When the supplied back-up extension starts with the full stop file
	 * separator ('.').
	 *
	 * @param fileLocation The file name and absolute directory path of the budget file. The text
	 * after the last directory separator is assumed to be the name of the budget file.
	 * @param backUpExtension (Optional) The extension to use when backing-up a pre-existing budget
	 * file. When this is not the default, it must not start with the full stop.
	 */
	explicit BudgetFile(
		const QString& fileLocation,
		const QString& backUpExtension = BudgetFile::defaultBackUpExtension_
	);
	/// The absolute directory path of the budget file.
	const QString& directoryPath() const;
	/// The file name of the budget file.
	const QString& name() const;
	/// The extension to use when backing-up a budget file.
	const QString& backUpExtension() const;
	/**
	 * @brief Loads the budget file.
	 *
	 * @exception Error When the budget file cannot be found.
	 *
	 * @return The the general ledger (first), fully loaded budget (second), the mapping between
	 * each budget item and its ledger account number (third), the financial institutions
	 * (fourth), and  the financial institution associations in the general ledger (fifth)
	 */
	std::tuple<
		drn::accounting::GeneralLedger,
		drn::budgeting::Budget,
		foundation::TypeIndexMap<budgeting::BudgetSource, accounting::AccountCode>,
		banking::BankMap,
		std::map<
			banking::BankName,
			std::map<accounting::AccountNumber, banking::SupportedAccountTypes>
		>
	> load() const;
	/**
	 * @brief Creates or overwrites the budget file. When overwriting the budget file, a back-up
	 * copy is created in the same directory.
	 *
	 * @exception Error When the budget file cannot be saved.
	 * @exception Error When the budget file cannot be backed-up prior to saving.
	 *
	 * @param[in] gl The general ledger whose contents are to be stored in the file.
	 * @param[in] b The budget whose contents are to be stored in the file.
	 * @param[in] budgetCodes The mapping between each budget item and its ledger account number.
	 * @param[in] banks The financial institutions whose contents are to be stored in the file.
	 * @param[in] bankAccountTypes The associations between the financial institutions and the
	 * general ledger whose contents are to be stored in the file.
	 */
	void store(
		const drn::accounting::GeneralLedger& gl,
		const drn::budgeting::Budget& b,
		const foundation::TypeIndexMap<
			budgeting::BudgetSource,
			accounting::AccountCode
		>& budgetCodes,
		const banking::BankMap& banks,
		const std::map<
			banking::BankName,
			std::map<accounting::AccountNumber, banking::SupportedAccountTypes>
		>& bankAccountTypes
	) const;
};

}}

#endif
