/*******************************************************************************
***  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/>.    ***
*******************************************************************************/
#include "Bank.h"
using std::set;
using ::QString;
using drn::accounting::AccountNumber;
using drn::banking::Bank;
using drn::banking::BankName;

#include <QObject>
using ::QObject;

#include <ostream>
using std::boolalpha;
using std::ostream;
#include <utility>
using std::move;

#include "BankingErrors.h"
using drn::banking::BankError;


Bank::Bank(BankName name, set<AccountNumber> numbers, const bool isClosed) :
	accountNumbers_{move(numbers)},
	isClosed_{isClosed},
	name_{move(name)}
{}

const set<AccountNumber>& Bank::accounts() const
{
	return this->accountNumbers_;
}

const bool& Bank::isClosed() const
{
	return this->isClosed_;
}

void Bank::close()
{
	if (this->isClosed_)
		throw BankError{this->name_, QObject::tr("Cannot close a bank that is already closed.")};
	this->isClosed_ = true;
}

void Bank::open()
{
	if ( ! this->isClosed_)
		throw BankError{this->name_, QObject::tr("Cannot open a bank that is already opened.")};
	this->isClosed_ = false;
}

void Bank::add(AccountNumber number)
{
	this->accountNumbers_.emplace(move(number));
}

void Bank::remove(const AccountNumber& number)
{
	if (this->accountNumbers_.erase(number) != 1)
		throw BankError{
			this->name_,
			QObject::tr(
				"The account '%1' is not associated with the financial institution."
			).arg(presentationText(number))
		};
}

bool drn::banking::operator==(const Bank& lhs, const Bank& rhs)
{
	if (&lhs == &rhs)
		return true;
	return lhs.isClosed() == rhs.isClosed() && lhs.name_ == rhs.name_
			&& lhs.accounts() == rhs.accounts();
}

bool drn:: banking::operator!=(const Bank& lhs, const Bank& rhs)
{
	return ! (lhs == rhs);
}

ostream& drn::banking::operator<<(ostream& o, const Bank& b)
{
	o << "Bank: (" << b.name_ << "), Account Numbers: (";

	bool isFirst{true};
	for (const auto& accountNumber : b.accounts())
			o << (isFirst ? isFirst = false, "" : ", ") << accountNumber;
	o << "), Is Closed: " << boolalpha << b.isClosed() << ')';
	return o;
}
