
package de.ivu.elect.util;

import static org.apache.commons.lang3.StringUtils.isNoneBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.trimToEmpty;
import static org.apache.commons.lang3.StringUtils.upperCase;

import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.Currency;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

public class MoneyUtil {

  private static final Map<String, String> SYMBOL_PER_CURRENCY_CODE = new HashMap<>();

  static {
    for (Locale locale : Locale.getAvailableLocales()) {
      if (isNotBlank(locale.getCountry())) {
        try {
          Currency currency = Currency.getInstance(locale);

          String currencyCode = upperCase(trimToEmpty(currency.getCurrencyCode())); // Cf. MoneyUtil#normalizeCurrencyCode!
          String symbol = currency.getSymbol(locale);

          if (isNoneBlank(currencyCode, symbol)) {
            SYMBOL_PER_CURRENCY_CODE.putIfAbsent(currencyCode, symbol);
          }
        } catch (Exception ignored) {
        }
      }
    }
  }

  private MoneyUtil() {
    super();
  }

  public static String formatBetragMitWaehrungskuerzel(Locale locale, BigDecimal value, String currencyCode) {
    return formatMitWaehrungskuerzel(locale, formatBetrag(locale, value), currencyCode);
  }

  public static String formatMitWaehrungskuerzel(Locale locale, String value, String currencyCode) {
    return formatMitWaehrung(value, formatWaehrungskuerzel(locale, currencyCode));
  }

  public static String formatWaehrungskuerzel(Locale locale, String currencyCode) {
    return upperCase(normalizeCurrencyCode(currencyCode), locale);
  }

  public static String formatBetragMitWaehrungssymbol(Locale locale, BigDecimal value, String currencyCode) {
    return formatMitWaehrungssymbol(locale, formatBetrag(locale, value), currencyCode);
  }

  public static String formatMitWaehrungssymbol(Locale locale, String value, String currencyCode) {
    return formatMitWaehrung(value, formatWaehrungssymbol(locale, currencyCode));
  }

  public static String formatWaehrungssymbol(Locale locale, String currencyCode) {
    return SYMBOL_PER_CURRENCY_CODE.getOrDefault(normalizeCurrencyCode(currencyCode), formatWaehrungskuerzel(locale, currencyCode));
  }

  private static String formatMitWaehrung(String value, String currency) {
    if (isNotBlank(value)) {
      return trimToEmpty(value + " " + currency);
    }

    return "";
  }

  public static String formatBetrag(Locale locale, BigDecimal value) {
    if (value == null) {
      return "";
    }

    NumberFormat numberFormat = NumberFormat.getInstance(locale);
    numberFormat.setMinimumFractionDigits(2);
    numberFormat.setMaximumFractionDigits(2);

    return numberFormat.format(normalizeBetrag(value));
  }

  private static String normalizeCurrencyCode(String currencyCode) {
    return upperCase(trimToEmpty(currencyCode));
  }

  private static BigDecimal normalizeBetrag(BigDecimal value) {
    return new BigDecimal(0).add(value).setScale(2, BigDecimal.ROUND_HALF_UP);
  }
}
