/*
 * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @bug 4290801 4692419 4693631 5101540 5104960 6296410 6336600 6371531
 *      6488442 7036905 8008577 8039317 8074350 8074351 8150324 8167143
 *      8264792 8334653 8353713
 * @summary Basic tests for Currency class.
 * @modules java.base/java.util:open
 *          jdk.localedata
 * @run junit CurrencyTest
 */

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Currency;
import java.util.List;
import java.util.Locale;
import java.util.stream.Stream;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;


public class CurrencyTest {

    // 'ISO4217-list-one.txt' should be up-to-date before testing
    @Test
    public void dataVersionTest() {
        CheckDataVersion.check();
    }

    @Nested
    class CodeValidationTests {
        // Calling getInstance() on equal currency codes should return equal currencies
        @ParameterizedTest
        @MethodSource("validCurrencies")
        public void validCurrencyTest(String currencyCode) {
            compareCurrencies(currencyCode);
        }

        private static Stream<String> validCurrencies() {
            return Stream.of("USD", "EUR", "GBP", "JPY", "CNY", "CHF");
        }

        // Calling getInstance() with an invalid currency code should throw an IAE
        @ParameterizedTest
        @MethodSource("non4217Currencies")
        public void invalidCurrencyTest(String currencyCode) {
            IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () ->
                    Currency.getInstance(currencyCode), "getInstance() did not throw IAE");
            assertEquals("The input currency code: \"%s\" is not a valid ISO 4217 code"
                    .formatted(currencyCode), ex.getMessage());
        }

        private static Stream<String> non4217Currencies() {
            return Stream.of("AQD", "US$");
        }

        // Provide 3 length code, but first 2 chars should not be able to index
        // the main table, thus resulting as incorrect country code
        @Test
        void invalidCountryInCodeTest() {
            IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () ->
                    Currency.getInstance("..A"), "getInstance() did not throw IAE");
            assertEquals("The country code: \"%s\" is not a valid ISO 3166 code"
                    .formatted(".."), ex.getMessage());
        }

        // Calling getInstance() with a currency code not 3 characters long should throw
        // an IAE
        @ParameterizedTest
        @MethodSource("invalidLengthCurrencies")
        public void invalidCurrencyLengthTest(String currencyCode) {
            IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () ->
                    Currency.getInstance(currencyCode), "getInstance() did not throw IAE");
            assertEquals("The input currency code: \"%s\" must have a length of 3 characters"
                    .formatted(currencyCode), ex.getMessage());
        }

        private static Stream<String> invalidLengthCurrencies() {
            return Stream.of("\u20AC", "", "12345");
        }
    }

    @Nested
    class FundsCodesTests {
        // Calling getInstance() on equal currency codes should return equal currencies
        @ParameterizedTest
        @MethodSource("fundsCodes")
        public void validCurrencyTest(String currencyCode) {
            compareCurrencies(currencyCode);
        }

        // Verify a currency has the expected fractional digits
        @ParameterizedTest
        @MethodSource("fundsCodes")
        public void fractionDigitTest(String currencyCode, int expectedFractionDigits) {
            compareFractionDigits(currencyCode, expectedFractionDigits);
        }

        // Verify a currency has the expected numeric code
        @ParameterizedTest
        @MethodSource("fundsCodes")
        public void numericCodeTest(String currencyCode, int ignored, int expectedNumeric) {
            int numeric = Currency.getInstance(currencyCode).getNumericCode();
            assertEquals(numeric, expectedNumeric, String.format(
                    "Wrong numeric code for currency %s, expected %s, got %s",
                    currencyCode, expectedNumeric, numeric));
        }

        private static Stream<Arguments> fundsCodes() {
            return Stream.of(
                    Arguments.of("BOV", 2, 984), Arguments.of("CHE", 2, 947),
                    Arguments.of("CHW", 2, 948), Arguments.of("CLF", 4, 990),
                    Arguments.of("COU", 2, 970), Arguments.of("MXV", 2, 979),
                    Arguments.of("USN", 2, 997), Arguments.of("UYI", 0, 940)
            );
        }
    }

    @Nested
    class LocaleMappingTests {

        // very basic test: most countries have their own currency, and then
        // their currency code is an extension of their country code.
        @Test
        public void localeMappingTest() {
            Locale[] locales = Locale.getAvailableLocales();
            int goodCountries = 0;
            int ownCurrencies = 0;
            for (Locale locale : locales) {
                String ctryCode = locale.getCountry();
                int ctryLength = ctryCode.length();
                if (ctryLength == 0 ||
                        ctryLength == 3 || // UN M.49 code
                        ctryCode.matches("AA|Q[M-Z]|X[A-JL-Z]|ZZ" + // user defined codes, excluding "XK" (Kosovo)
                                "AC|CP|DG|EA|EU|FX|IC|SU|TA|UK")) { // exceptional reservation codes
                    IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
                            () -> Currency.getInstance(locale), "Did not throw IAE");
                    assertEquals("The country of the input locale: \"%s\" is not a valid ISO 3166 country code"
                            .formatted(locale), ex.getMessage());
                } else {
                    goodCountries++;
                    Currency currency = Currency.getInstance(locale);
                    if (currency.getCurrencyCode().indexOf(locale.getCountry()) == 0) {
                        ownCurrencies++;
                    }
                }
            }
            System.out.println("Countries tested: " + goodCountries +
                    ", own currencies: " + ownCurrencies);
            if (ownCurrencies < (goodCountries / 2 + 1)) {
                throw new RuntimeException("suspicious: not enough countries have their own currency.");
            }
        }

        // Check an invalid country code supplied via the region override
        @Test
        public void invalidCountryRegionOverrideTest() {
            // Override US with nonsensical country
            var loc = Locale.forLanguageTag("en-US-u-rg-XXzzzz");
            IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
                    ()-> Currency.getInstance(loc), "Did not throw IAE");
            assertEquals("The country of the input locale: \"%s\" is not a valid ISO 3166 country code"
                    .formatted(loc), ex.getMessage());
        }

        // Ensure a selection of countries have the expected currency
        @ParameterizedTest
        @MethodSource({"countryProvider", "switchedOverCountries"})
        public void countryCurrencyTest(String countryCode, String expected) {
            Locale locale = Locale.of("", countryCode);
            Currency currency = Currency.getInstance(locale);
            String code = (currency != null) ? currency.getCurrencyCode() : null;
            assertEquals(expected, code, generateErrMsg(
                    "currency for", locale.getDisplayCountry(), expected, code));
        }

        private static Stream<Arguments> countryProvider() {
            return Stream.of(
                    // Check country that does not have a currency
                    Arguments.of("AQ", null),
                    // Check some countries that don't change their currencies often
                    Arguments.of("US", "USD"),
                    Arguments.of("CA", "CAD"),
                    Arguments.of("JP", "JPY"),
                    Arguments.of("CN", "CNY"),
                    Arguments.of("SG", "SGD"),
                    Arguments.of("CH", "CHF")
            );
        }

        /*
         * Check Currency Changes
         * In the current implementation, there is no data of old currency and transition
         * date at jdk/src/java.base/share/data/currency/CurrencyData.properties.
         * So, all the switch data arrays are empty. In the future, if data of old
         * currency and transition date are necessary for any country, the
         * arrays here can be updated so that the program can check the currency switch.
         */
        private static List<Arguments> switchedOverCountries() {
            List<Arguments> switched = new ArrayList<Arguments>();
            String[] switchOverCtry = {};
            String[] switchOverOld = {};
            String[] switchOverNew = {};
            String[] switchOverTZ = {};
            int[] switchOverYear = {};
            int[] switchOverMonth = {}; // java.time APIs accept month starting from 1 i.e. 01 for January
            int[] switchOverDay = {};

            for (int i = 0; i < switchOverCtry.length; i++) {
                ZoneId zoneId = ZoneId.of(switchOverTZ[i]);
                ZonedDateTime zonedDateAndTime  = ZonedDateTime.of(LocalDate.of(
                        switchOverYear[i], switchOverMonth[i], switchOverDay[i]), LocalTime.MIDNIGHT, zoneId);
                ZonedDateTime currentZonedDateAndTime =  ZonedDateTime.now(zoneId);
                switched.add(Arguments.of(switchOverCtry[i], (currentZonedDateAndTime.isAfter(zonedDateAndTime)
                        || currentZonedDateAndTime.isEqual(zonedDateAndTime)) ? switchOverNew[i] : switchOverOld[i]));
            }
            return switched;
        }
    }

    // NON-NESTED TESTS

    // Ensure selection of currencies have the correct fractional digits
    @ParameterizedTest
    @MethodSource("expectedFractionsProvider")
    public void fractionDigitsTest(String currencyCode, int expectedFractionDigits) {
        compareFractionDigits(currencyCode, expectedFractionDigits);
    }

    private static Stream<Arguments> expectedFractionsProvider() {
        return Stream.of(
                Arguments.of("USD", 2), Arguments.of("EUR", 2),
                Arguments.of("JPY", 0), Arguments.of("XDR", -1),
                Arguments.of("BHD", 3), Arguments.of("IQD", 3),
                Arguments.of("JOD", 3), Arguments.of("KWD", 3),
                Arguments.of("LYD", 3), Arguments.of("OMR", 3),
                Arguments.of("TND", 3),

                // Old and New Turkish Lira
                Arguments.of("TRL", 0), Arguments.of("TRY", 2)
        );
    }

    // Ensure selection of currencies have the expected symbol
    @ParameterizedTest
    @MethodSource("symbolProvider")
    public void symbolTest(String currencyCode, Locale locale, String expectedSymbol) {
        String symbol = Currency.getInstance(currencyCode).getSymbol(locale);
        assertEquals(symbol, expectedSymbol, generateErrMsg(
                "symbol for", currencyCode, expectedSymbol, symbol));
    }

    private static Stream<Arguments> symbolProvider() {
        return Stream.of(
                Arguments.of("USD", Locale.US, "$"),
                Arguments.of("EUR", Locale.GERMANY, "\u20AC"),
                Arguments.of("USD", Locale.PRC, "US$")
        );
    }

    // Ensure serialization does not break class invariant.
    // Currency should be able to round-trip and remain the same value.
    @Test
    public void serializationTest() throws Exception {
        Currency currency1 = Currency.getInstance("DEM");

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oStream = new ObjectOutputStream(baos);
        oStream.writeObject(currency1);
        oStream.flush();
        byte[] bytes = baos.toByteArray();

        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        ObjectInputStream iStream = new ObjectInputStream(bais);
        Currency currency2 = (Currency) iStream.readObject();
        assertEquals(currency1, currency2, "serialization breaks class invariant");
    }

    // Ensure getInstance() throws null when passed a null locale
    @Test
    public void nullDisplayNameTest() {
        assertThrows(NullPointerException.class, ()->
                Currency.getInstance("USD").getDisplayName(null));
    }

    // Ensure a selection of currencies/locale combos have the correct display name
    @ParameterizedTest
    @MethodSource("displayNameProvider")
    public void displayNameTest(String currencyCode, Locale locale, String expectedName) {
        String name = Currency.getInstance(currencyCode).getDisplayName(locale);
        assertEquals(name, expectedName, generateErrMsg(
                "display name for", currencyCode, expectedName, name));
    }

    private static Stream<Arguments> displayNameProvider() {
        return Stream.of(
                Arguments.of("USD", Locale.ENGLISH, "US Dollar"),
                Arguments.of("FRF", Locale.FRENCH, "franc fran\u00e7ais"),
                Arguments.of("DEM", Locale.GERMAN, "Deutsche Mark"),
                Arguments.of("ESP", Locale.of("es"), "peseta espa\u00f1ola"),
                Arguments.of("ITL", Locale.ITALIAN, "lira italiana"),
                Arguments.of("JPY", Locale.JAPANESE, "\u65e5\u672c\u5186"),
                Arguments.of("KRW", Locale.KOREAN, "\ub300\ud55c\ubbfc\uad6d \uc6d0"),
                Arguments.of("SEK", Locale.of("sv"), "svensk krona"),
                Arguments.of("CNY", Locale.SIMPLIFIED_CHINESE, "\u4eba\u6c11\u5e01"),
                Arguments.of("TWD", Locale.TRADITIONAL_CHINESE, "\u65b0\u53f0\u5e63")
        );
    }

    // HELPER FUNCTIONS

    // A Currency instance returned from getInstance() should always be
    // equal if supplied the same currencyCode. getCurrencyCode() should
    // always be equal to the currencyCode used to create the Currency.
    private static void compareCurrencies(String currencyCode) {
        Currency currency1 = Currency.getInstance(currencyCode);
        Currency currency2 = Currency.getInstance(currencyCode);
        assertEquals(currency1, currency2, "Didn't get same instance for same currency code");
        assertEquals(currency1.getCurrencyCode(), currencyCode, "getCurrencyCode()" +
                " did not return the expected value");
    }

    // Ensures the getDefaultFractionDigits() method returns the expected amount
    private static void compareFractionDigits(String currencyCode,
                                              int expectedFractionDigits) {
        int digits = Currency.getInstance(currencyCode).getDefaultFractionDigits();
        assertEquals(digits, expectedFractionDigits, generateErrMsg(
                "number of fraction digits for currency",
                currencyCode, Integer.toString(expectedFractionDigits), Integer.toString(digits)));
    }

    // Used for logging on failing tests
    private static String generateErrMsg(String subject, String currency,
                                         String expected, String got) {
        return String.format("Wrong %s %s: expected '%s', got '%s'",
                subject, currency, expected, got);
    }
}
