/*******************************************************************************
***  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 "BankAccountType.h"
using std::array;
using drn::banking::SupportedAccountTypes;
using drn::banking::numberOfSupportedAccountTypes;

#include <QString>
using ::QString;

#include <ostream>
using std::ostream;
#include <tuple>
using std::tie;

#include <accounting/Account.h>
using drn::accounting::AccountTypes;
#include <foundation/EnumMacros.hpp>
// using BEGIN_OTHER_TO_ENUMERATION
// using BEGIN_ENUMERATION_TO_OTHER
// using END_OTHER_TO_ENUMERATION
// using MAP_OTHER_TO_ENUMERATION


SupportedAccountTypes drn::banking::toSupportedAccountTypes(const QString& bankAccountType)
{
	BEGIN_OTHER_TO_ENUMERATION(SupportedAccountTypes);
		MAP_OTHER_TO_ENUMERATION(bankAccountType, "Chequeing", SupportedAccountTypes::Chequeing);
		MAP_OTHER_TO_ENUMERATION(bankAccountType, "Goal", SupportedAccountTypes::Goal);
		MAP_OTHER_TO_ENUMERATION(bankAccountType, "Credit Card", SupportedAccountTypes::CreditCard);
		MAP_OTHER_TO_ENUMERATION(bankAccountType, "Loan", SupportedAccountTypes::Loan);
		MAP_OTHER_TO_ENUMERATION(bankAccountType, "Savings", SupportedAccountTypes::Savings);
		MAP_OTHER_TO_ENUMERATION(bankAccountType, "Unknown", SupportedAccountTypes::Unknown);
	END_OTHER_TO_ENUMERATION(bankAccountType, SupportedAccountTypes);
}

QString drn::banking::presentationText(const SupportedAccountTypes& sat)
{
	BEGIN_ENUMERATION_TO_OTHER(sat)
		MAP_ENUMERATION_TO_OTHER(SupportedAccountTypes::Chequeing, "Chequeing");
		MAP_ENUMERATION_TO_OTHER(SupportedAccountTypes::Goal, "Goal");
		MAP_ENUMERATION_TO_OTHER(SupportedAccountTypes::CreditCard, "Credit Card");
		MAP_ENUMERATION_TO_OTHER(SupportedAccountTypes::Loan, "Loan");
		MAP_ENUMERATION_TO_OTHER(SupportedAccountTypes::Savings, "Savings");
		MAP_ENUMERATION_TO_OTHER(SupportedAccountTypes::Unknown, "Unknown");
	END_ENUMERATION_TO_OTHER(sat, SupportedAccountTypes)
}

AccountTypes drn::banking::toAccountTypes(const SupportedAccountTypes& type)
{
	BEGIN_ENUMERATION_TO_OTHER(type)
		MAP_ENUMERATION_TO_OTHER(SupportedAccountTypes::Chequeing, AccountTypes::Asset);
		MAP_ENUMERATION_TO_OTHER(SupportedAccountTypes::Goal, AccountTypes::Unknown);
		MAP_ENUMERATION_TO_OTHER(SupportedAccountTypes::CreditCard, AccountTypes::Liability);
		MAP_ENUMERATION_TO_OTHER(SupportedAccountTypes::Loan, AccountTypes::Liability);
		MAP_ENUMERATION_TO_OTHER(SupportedAccountTypes::Savings, AccountTypes::Asset);
		MAP_ENUMERATION_TO_OTHER(SupportedAccountTypes::Unknown, AccountTypes::Unknown);
	END_ENUMERATION_TO_OTHER(type, SupportedAccountTypes)
}

ostream& drn::banking::operator<<(ostream& o, const SupportedAccountTypes& sat)
{
	return o << presentationText(sat).toStdString();
}

bool drn::banking::operator<(const BankAccountType& lhs, const BankAccountType& rhs)
{
	return tie(lhs.type_, lhs.code_) < tie(rhs.type_, rhs.code_);
}

bool drn::banking::operator==(const BankAccountType& lhs, const BankAccountType& rhs)
{
	return tie(lhs.type_, lhs.code_) == tie(rhs.type_, rhs.code_);
}

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

ostream& drn::banking::operator<<(ostream& out, const BankAccountType& bat)
{
	return out << "Account Code (" << bat.code_ << "), Supported Account Type (" << bat.type_
			<< ')';
}

const array<
	SupportedAccountTypes,
	numberOfSupportedAccountTypes
> drn::banking::allSupportedAccountTypes{
	SupportedAccountTypes::Unknown,
	SupportedAccountTypes::Chequeing,
	SupportedAccountTypes::Goal,
	SupportedAccountTypes::CreditCard,
	SupportedAccountTypes::Loan,
	SupportedAccountTypes::Savings
};
