/*
 * Copyright (C) 2014-2021 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 <QList>

#include "src/datovka_shared/settings/account_container.h"
#include "src/settings/account.h"

class AcntId; /* Forward declaration. */

/*!
 * @brief Holds account data.
 */
class AccountsMap : public AcntSettingsMap<AcntData> {
	/* This class is just generated from a template. */
private:
	/* Prohibit some parent class methods. */
	using AcntSettingsMap<AcntData>::operator[];
	using AcntSettingsMap<AcntData>::contains;
	using AcntSettingsMap<AcntData>::remove;
	using AcntSettingsMap<AcntData>::find;
	using AcntSettingsMap<AcntData>::end;

public:
	using AcntSettingsMap<AcntData>::AcntSettingsMap;

	/*!
	 * @brief Load data from another container. The container must hold same
	 *     account type (regular or shadow).
	 *
	 * @note Emits contentAboutToBeReset() and contentReset().
	 *
	 * @param[in] other Container to load data from.
	 */
	void load(const AccountsMap &other);

	/*!
	 * @brief Load data from supplied settings.
	 *
	 * @param[in] confDir Configuration directory path.
	 * @param[in] settings Settings structure to be read.
	 *
	 * @note Emits contentAboutToBeReset() and contentReset().
	 */
	void loadFromSettings(const QString &confDir,
	    const QSettings &settings);

	/*!
	 * @brief Store data to settings structure.
	 *
	 * @param[in]  pinVal PIN value to be used for password encryption.
	 * @param[in]  confDir Configuration directory path.
	 * @param[out] settings Setting structure to store the model content
	 *     into.
	 */
	void saveToSettings(const QString &pinVal, const QString &confDir,
	    QSettings &settings) const;

	/*!
	 * @brief Get account identifiers.
	 *
	 * @return List of account identifiers.
	 */
	const QList<AcntId> &acntIds(void) const;

	/*!
	 * @brief Return account data.
	 *
	 * @param[in] acntId Account identifier.
	 * @return Account data.
	 */
	AcntData acntData(const AcntId &acntId) const;

	/*!
	 * @brief Adds account data.
	 *
	 * @note Emits accountAboutToBeAdded() and accountAdded().
	 *
	 * @param[in] acntData New account data.
	 * @return -2 if account already exists,
	 *         -1 if account could not be added,
	 *          0 if account was added.
	 */
	int addAccount(const AcntData &acntData);

	/*!
	 * @brief Update account data of existing account.
	 *
	 * @note Emits accountDataChanged().
	 *
	 * @param[in] acntData Update account data.
	 */
	void updateAccount(const AcntData &acntData);

	/*!
	 * @brief Update account data including the username.
	 *
	 * @note Emits accountUsernameChanged().
	 *
	 * @param[in] oldId Old account identifier.
	 * @param[in] newData New account data.
	 */
	void updateUsernameAccount(const AcntId &oldId, const AcntData &newData);

	/*!
	 * @brief Removes account data.
	 *
	 * @note Emits accountAboutToBeRemoved() and accountRemoved().
	 * @note The usage of a parameter copy is intentional to prevent any
	 *     accidental use after free situations when an account identifier
	 *     from the container is used.
	 *
	 * @param[in] acntId Account identifier.
	 */
	void removeAccount(const AcntId acntId);

	/*!
	 * @brief Changes the order of the accounts.
	 *
	 * @note Emits accountsAboutToBeMoved() and accountsMoved().
	 * @note See documentation of QAbstractItemModel::beginMoveRows() for
	 *     details how the parameters work.
	 *
	 * @param[in] srcIdx First account index.
	 * @param[in] srcCnt Length of the moved sequence.
	 * @param[in] dstIdx Destination index.
	 */
	bool moveAccounts(int srcIdx, int srcCnt, int dstIdx);

private:
	QList<AcntId> m_acntIds; /*!<
	                          * List of account identifiers that are used
	                          * to access the global accounts.
	                          */
};

/*!
 * @brief Return account identifier from account data.
 *
 * @param[in] acntData Account data.
 * @rerturn Account identifier.
 */
AcntId acntIdFromData(const AcntData &acntData);
