/*******************************************************************************
***  This file is part of Pecunia.                                           ***
***                                                                          ***
***  Copyright (C) 2017, 2018, 2019, 2020, 2021, 2023                        ***
***  John Schneiderman <Licencing _AT_ Schneiderman _DOT_ me>                ***
***                                                                          ***
***  This program is free software: you can redistribute it and/or modify it ***
***  under the terms of the GNU Lesser 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 Lesser General Public License for more details.             ***
***                                                                          ***
***  You should have received a copy of the GNU Lesser General Public License***
***  along with this program. If not, see <http://www.gnu.org/licenses/>.    ***
*******************************************************************************/
#include <QObject>
using ::QObject;
#include <QTest>
// using QTEST_MAIN;

#include <exception>
using std::exception;
#include <string>
using std::string;
#include <vector>
using std::vector;

#include <pecunia/Codes.h>
using pecunia::currency::allIso4217Codes;
using pecunia::currency::Iso4217Codes;
using pecunia::currency::countriesUsing;
using pecunia::currency::currencyName;
using pecunia::currency::minorUnitPrecisionFactor;
using pecunia::currency::numberOfIso4217Codes;
using pecunia::currency::toStdString;
using pecunia::currency::toIso4217Code;
using pecunia::currency::currencySymbol;


namespace pecunia
{
namespace currency
{
namespace tests
{

struct CodesUT : QObject
{
	Q_OBJECT

private slots:
	//{ toStdString tests

	void toStdString_XXX_ShouldBeXXX()
	{
		string iso4217{toStdString(Iso4217Codes::XXX)};
		QCOMPARE(iso4217.c_str(), string{"XXX"}.c_str());
	}
	void toStdString_USD_ShouldBeUSD()
	{
		string iso4217{toStdString(Iso4217Codes::USD)};
		QCOMPARE(iso4217.c_str(), string{"USD"}.c_str());
	}
	void toStdString_PLN_ShouldBePLN()
	{
		string iso4217{toStdString(Iso4217Codes::PLN)};
		QCOMPARE(iso4217.c_str(), string{"PLN"}.c_str());
	}

	//}

	//{ minorUnitPrecisionFactor tests

	void minorUnitPrecisionFactorXxxPrecision2_ShouldBe100()
	{
		const auto ratio(minorUnitPrecisionFactor(Iso4217Codes::XXX));
		// 0 for minor and 2 for precision.
		QCOMPARE(ratio, 100);
	}
	void minorUnitPrecisionFactorUsdPrecision2_ShouldBe10000()
	{
		const auto ratio(minorUnitPrecisionFactor(Iso4217Codes::USD));
		// 2 for minor and 2 for precision.
		QCOMPARE(ratio, 10000);
	}

	//}

	//{ currencySymbol tests

	void currencySymbol_USD_ShouldBeDollarSign()
	{
		string iso4217{currencySymbol(Iso4217Codes::USD)};
		QCOMPARE(iso4217.c_str(), string{"$"}.c_str());
	}
	void currencySymbol_PLN_ShouldBeZloty()
	{
		string iso4217{currencySymbol(Iso4217Codes::PLN)};
		QCOMPARE(iso4217.c_str(), string{"zł"}.c_str());
	}

	//}

	//{ toIso4217Code tests

	void toIso4217Code_XXX_ShouldBeNoCurrencyInvolved()
	{
		Iso4217Codes iso4217{toIso4217Code("XXX")};
		QCOMPARE(iso4217, Iso4217Codes::XXX);
	}
	void toIso4217Code_USD_ShouldBeDollarSign()
	{
		Iso4217Codes iso4217{toIso4217Code("USD")};
		QCOMPARE(iso4217, Iso4217Codes::USD);
	}
	void toIso4217Code_PLN_ShouldBeZloty()
	{
		Iso4217Codes iso4217{toIso4217Code("PLN")};
		QCOMPARE(iso4217, Iso4217Codes::PLN);
	}
	void toIso4217Code_Invalid_ShouldThrow()
	{
		QVERIFY_EXCEPTION_THROWN(toIso4217Code("I am a fake code"), std::runtime_error);
	}
	void toIso4217Code_usd_ShouldThrow()
	{
		QVERIFY_EXCEPTION_THROWN(toIso4217Code("usd"), std::runtime_error);
	}

	//}

	//{ allCodes tests

	void allCodes_InterateThroughAll_ShouldNotThrow()
	{
		for (size_t index{0}; index < numberOfIso4217Codes; ++index)
			Q_UNUSED(allIso4217Codes.at(index))
	}

	void allCodes_PastLastOne_ShouldThrow()
	{
		try
		{
			Q_UNUSED(allIso4217Codes.at(numberOfIso4217Codes));
			QVERIFY2(false, "Expected exception did not throw.");
		}
		catch (const exception&)
		{
			QVERIFY(true);
		}
	}

	//}

	//{ countriesUsing tests

	void countriesUsing_knownCurrency_ShouldGive()
	{
		const vector<string> expected{
			"AMERICAN SAMOA",
			"BONAIRE, SINT EUSTATIUS AND SABA",
			"BRITISH INDIAN OCEAN TERRITORY (THE)",
			"ECUADOR",
			"EL SALVADOR",
			"GUAM",
			"HAITI",
			"MARSHALL ISLANDS (THE)",
			"MICRONESIA (FEDERATED STATES OF)",
			"NORTHERN MARIANA ISLANDS (THE)",
			"PALAU",
			"PANAMA",
			"PUERTO RICO",
			"TIMOR-LESTE",
			"TURKS AND CAICOS ISLANDS (THE)",
			"UNITED STATES MINOR OUTLYING ISLANDS (THE)",
			"UNITED STATES OF AMERICA (THE)",
			"VIRGIN ISLANDS (BRITISH)",
			"VIRGIN ISLANDS (U.S.)"
		};
		QCOMPARE(countriesUsing(Iso4217Codes::USD), expected);
	}

	//}

	//{ currencyName tests

	void currencyName_knownCurrency_ShouldGive()
	{
		const string expected{"US Dollar"};
		QCOMPARE(currencyName(Iso4217Codes::USD), expected);
	}

	//}
};

}}}

QTEST_MAIN(pecunia::currency::tests::CodesUT)
#include "codes-unit-tests.moc"
