/*******************************************************************************
***  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/>.    ***
*******************************************************************************/
#ifndef PECUNIA_CURRENCY_CODES_H_
#define PECUNIA_CURRENCY_CODES_H_

//  ██████╗  ██████╗     ███╗   ██╗ ██████╗ ████████╗    ███████╗██████╗ ██╗████████╗██╗
//  ██╔══██╗██╔═══██╗    ████╗  ██║██╔═══██╗╚══██╔══╝    ██╔════╝██╔══██╗██║╚══██╔══╝██║
//  ██║  ██║██║   ██║    ██╔██╗ ██║██║   ██║   ██║       █████╗  ██║  ██║██║   ██║   ██║
//  ██║  ██║██║   ██║    ██║╚██╗██║██║   ██║   ██║       ██╔══╝  ██║  ██║██║   ██║   ╚═╝
//  ██████╔╝╚██████╔╝    ██║ ╚████║╚██████╔╝   ██║       ███████╗██████╔╝██║   ██║   ██╗
//  ╚═════╝  ╚═════╝     ╚═╝  ╚═══╝ ╚═════╝    ╚═╝       ╚══════╝╚═════╝ ╚═╝   ╚═╝   ╚═╝
//
//  ███████╗██╗██╗     ███████╗     ██████╗ ██████╗ ███╗   ██╗████████╗███████╗███╗   ██╗████████╗
//  ██╔════╝██║██║     ██╔════╝    ██╔════╝██╔═══██╗████╗  ██║╚══██╔══╝██╔════╝████╗  ██║╚══██╔══╝
//  █████╗  ██║██║     █████╗      ██║     ██║   ██║██╔██╗ ██║   ██║   █████╗  ██╔██╗ ██║   ██║
//  ██╔══╝  ██║██║     ██╔══╝      ██║     ██║   ██║██║╚██╗██║   ██║   ██╔══╝  ██║╚██╗██║   ██║
//  ██║     ██║███████╗███████╗    ╚██████╗╚██████╔╝██║ ╚████║   ██║   ███████╗██║ ╚████║   ██║
//  ╚═╝     ╚═╝╚══════╝╚══════╝     ╚═════╝ ╚═════╝ ╚═╝  ╚═══╝   ╚═╝   ╚══════╝╚═╝  ╚═══╝   ╚═╝
//
//   ██████╗██████╗ ███████╗ █████╗ ████████╗██╗ ██████╗ ███╗   ██╗    ██╗███████╗
//  ██╔════╝██╔══██╗██╔════╝██╔══██╗╚══██╔══╝██║██╔═══██╗████╗  ██║    ██║██╔════╝
//  ██║     ██████╔╝█████╗  ███████║   ██║   ██║██║   ██║██╔██╗ ██║    ██║███████╗
//  ██║     ██╔══██╗██╔══╝  ██╔══██║   ██║   ██║██║   ██║██║╚██╗██║    ██║╚════██║
//  ╚██████╗██║  ██║███████╗██║  ██║   ██║   ██║╚██████╔╝██║ ╚████║    ██║███████║
//   ╚═════╝╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝   ╚═╝   ╚═╝ ╚═════╝ ╚═╝  ╚═══╝    ╚═╝╚══════╝
//
//   █████╗ ██╗   ██╗████████╗ ██████╗ ███╗   ███╗ █████╗ ████████╗███████╗██████╗
//  ██╔══██╗██║   ██║╚══██╔══╝██╔═══██╗████╗ ████║██╔══██╗╚══██╔══╝██╔════╝██╔══██╗
//  ███████║██║   ██║   ██║   ██║   ██║██╔████╔██║███████║   ██║   █████╗  ██║  ██║
//  ██╔══██║██║   ██║   ██║   ██║   ██║██║╚██╔╝██║██╔══██║   ██║   ██╔══╝  ██║  ██║
//  ██║  ██║╚██████╔╝   ██║   ╚██████╔╝██║ ╚═╝ ██║██║  ██║   ██║   ███████╗██████╔╝██╗
//  ╚═╝  ╚═╝ ╚═════╝    ╚═╝    ╚═════╝ ╚═╝     ╚═╝╚═╝  ╚═╝   ╚═╝   ╚══════╝╚═════╝ ╚═╝
// Generated At: @TIMESTAMP@

#include <array>
#include <cstdint>
#include <ostream>
#include <string>
#include <vector>

#include <pecunia_export.h> // cppcheck-suppress missingInclude


namespace pecunia
{
namespace currency
{

/**
 * @brief The unique identifier for a country's currency, monetary market, etc..
 *
 * @see ISO 4217 https://en.wikipedia.org/wiki/ISO_4217
 */
enum class PECUNIA_EXPORT Iso4217Codes : std::uint16_t
{
@ENUM_CODES@
};

/**
 * @brief Converts from a strongly-typed ISO code to a weak string form.
 *
 * @param[in] code The country's monetary unit whose ISO code is to be converted.
 *
 * @return The weak type form of the ISO code.
 */
PECUNIA_EXPORT std::string toStdString(const Iso4217Codes& code);
/**
 * @brief Converts from a weakly-typed ISO code to the strongly-typed form. The code must be all
 * upper-cased for the match to be performed.
 *
 * @exception std::runtime_error When the supplied weak code does not match any known strong code.
 *
 * @param[in] code The country's monetary unit whose ISO code is to be converted.
 *
 * @return The strong type form of the ISO code.
 */
PECUNIA_EXPORT Iso4217Codes toIso4217Code(const std::string& code);
/**
 * @brief Provides the native currency symbol used by a currency code. N.B. currency symbols are
 * shared by others and are therefore cannot be unique.
 *
 * @note Currently not all codes are supported.
 *
 * @param[in] code The country's monetary unit whose currency symbol is desired.
 *
 * @return The string representation of the currency symbol.
 */
PECUNIA_EXPORT std::string currencySymbol(const Iso4217Codes& code);
/**
 * @brief Provides the number of digits used by the minor currency unit using the currency's
 * ISO exponent.
 *
 * @param[in] code The country's monetary unit whose number of digits is desired.
 *
 * @return The number of digits used by the minor currency unit.
 */
PECUNIA_EXPORT std::uint8_t minorUnitDigits(const Iso4217Codes& code);
/**
 * @brief Calculates the currency factor between the major unit and the minor unit accounting for
 * the system precision of the minor monetary unit. The precision is in terms of how many extra
 * digits to add for the minor unit, e.g. USD starts with 2 and a precision of 2 would provide
 * for a total precision of 4 digits.
 *
 * @param[in] code The country's monetary unit to calculate the ratio for.
 *
 * @return The multiplicative factor between the major and minor unit with a supplied precision.
 */
PECUNIA_EXPORT std::int32_t minorUnitPrecisionFactor(const Iso4217Codes& code);
/**
* @brief Performs the stream insertion for displaying the currency code in the ISO-4217 form.
*
* @param stream The stream into which the code should be inserted.
* @param code The code that will be inserted.
*
* @return The same stream that was supplied, but now containing the code.
*/
PECUNIA_EXPORT std::ostream& operator<<(std::ostream& stream, const Iso4217Codes& code);
/**
 * @brief Looks-up the countries which are using a given currency.
 *
 * @param code The code of the currency to look-up for all the countries.
 *
 * @return All the countries found.
 */
PECUNIA_EXPORT std::vector<std::string> countriesUsing(const Iso4217Codes& code);
/**
 * @brief Looks-up the name of a currency using a given currency code.
 *
 * @param code The code of the currency to look-up for its name.
 *
 * @return The name of the currency in English.
 */
PECUNIA_EXPORT std::string currencyName(const Iso4217Codes& code);

/// The total number of currency codes supported.
constexpr std::uint8_t numberOfIso4217Codes{@NUMBER_OF_CODES@};
/// A container of every currency code supported. The codes are all other codes in alphabetical
/// order.
extern PECUNIA_EXPORT const std::array<Iso4217Codes, numberOfIso4217Codes> allIso4217Codes;

}}

#endif
