// © 2020 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html


package com.ibm.icu.impl.units;

import java.util.ArrayList;
import java.util.HashMap;

import com.ibm.icu.impl.ICUData;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.UResource;
import com.ibm.icu.util.MeasureUnit;
import com.ibm.icu.util.UResourceBundle;

/**
 * Responsible for all units data operations (retriever, analysis, extraction certain data ... etc.).
 */
public class UnitsData {
    private volatile static String[] simpleUnits = null;
    private ConversionRates conversionRates;
    private UnitPreferences unitPreferences;
    /**
     * Pairs of categories and the corresponding base units.
     */
    private Categories categories;

    public UnitsData() {
        this.conversionRates = new ConversionRates();
        this.unitPreferences = new UnitPreferences();
        this.categories = new Categories();
    }

    public static String[] getSimpleUnits() {
        if (simpleUnits != null) {
            return simpleUnits;
        }

        // Read simple units
        ICUResourceBundle resource;
        resource = (ICUResourceBundle) UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, "units");
        SimpleUnitIdentifiersSink sink = new SimpleUnitIdentifiersSink();
        resource.getAllItemsWithFallback("convertUnits", sink);
        simpleUnits = sink.simpleUnits;

        return simpleUnits;
    }

    public ConversionRates getConversionRates() {
        return conversionRates;
    }

    public UnitPreferences getUnitPreferences() {
        return unitPreferences;
    }

    /**
     * @param measureUnit An instance of MeasureUnitImpl.
     * @return the corresponding category.
     */
    public String getCategory(MeasureUnitImpl measureUnit) {
        MeasureUnitImpl baseMeasureUnit
                = this.getConversionRates().extractCompoundBaseUnit(measureUnit);
        String baseUnitIdentifier = MeasureUnit.fromMeasureUnitImpl(baseMeasureUnit).getIdentifier();

        if (baseUnitIdentifier.equals("meter-per-cubic-meter")) {
            // TODO(CLDR-13787,hugovdm): special-casing the consumption-inverse
            // case. Once CLDR-13787 is clarified, this should be generalised (or
            // possibly removed):

            return "consumption-inverse";
        }

        return this.categories.mapFromUnitToCategory.get(baseUnitIdentifier);
    }

    public UnitPreferences.UnitPreference[] getPreferencesFor(String category, String usage, String region) {
        return this.unitPreferences.getPreferencesFor(category, usage, region);
    }

    public static class SimpleUnitIdentifiersSink extends UResource.Sink {
        String[] simpleUnits = null;

        @Override
        public void put(UResource.Key key, UResource.Value value, boolean noFallback) {
            assert key.toString().equals(Constants.CONVERSION_UNIT_TABLE_NAME);
            assert value.getType() == UResourceBundle.TABLE;

            UResource.Table simpleUnitsTable = value.getTable();
            ArrayList<String> simpleUnits = new ArrayList<>();
            for (int i = 0; simpleUnitsTable.getKeyAndValue(i, key, value); i++) {
                if (key.toString().equals("kilogram")) {

                    // For parsing, we use "gram", the prefixless metric mass unit. We
                    // thus ignore the SI Base Unit of Mass: it exists due to being the
                    // mass conversion target unit, but not needed for MeasureUnit
                    // parsing.
                    continue;
                }

                simpleUnits.add(key.toString());
            }

            this.simpleUnits = simpleUnits.toArray(new String[0]);
        }
    }

    /**
     * Contains all the needed constants.
     */
    public static class Constants {
        // TODO: consider moving the Trie-offset-related constants into
        // MeasureUnitImpl.java, the only place they're being used?

        // Trie value offset for simple units, e.g. "gram", "nautical-mile",
        // "fluid-ounce-imperial".
        public static final int kSimpleUnitOffset = 512;

        // Trie value offset for powers like "square-", "cubic-", "pow2-" etc.
        public static final int kPowerPartOffset = 256;


        // Trie value offset for "per-".
        public final static int kInitialCompoundPartOffset = 192;

        // Trie value offset for compound parts, e.g. "-per-", "-", "-and-".
        public final static int kCompoundPartOffset = 128;

        // Trie value offset for SI or binary prefixes. This is big enough to
        // ensure we only insert positive integers into the trie.
        public static final int kPrefixOffset = 64;


        /* Tables Names*/
        public static final String CONVERSION_UNIT_TABLE_NAME = "convertUnits";
        public static final String UNIT_PREFERENCE_TABLE_NAME = "unitPreferenceData";
        public static final String CATEGORY_TABLE_NAME = "unitQuantities";
        public static final String DEFAULT_REGION = "001";
        public static final String DEFAULT_USAGE = "default";
    }

    public static class Categories {

        /**
         * Contains the map between units in their base units into their category.
         * For example:  meter-per-second --> "speed"
         */
        HashMap<String, String> mapFromUnitToCategory;


        public Categories() {
            // Read unit Categories
            ICUResourceBundle resource;
            resource = (ICUResourceBundle) UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, "units");
            CategoriesSink sink = new CategoriesSink();
            resource.getAllItemsWithFallback(Constants.CATEGORY_TABLE_NAME, sink);
            this.mapFromUnitToCategory = sink.getMapFromUnitToCategory();
        }
    }

    public static class CategoriesSink extends UResource.Sink {
        /**
         * Contains the map between units in their base units into their category.
         * For example:  meter-per-second --> "speed"
         */
        HashMap<String, String> mapFromUnitToCategory;

        public CategoriesSink() {
            mapFromUnitToCategory = new HashMap<>();
        }

        @Override
        public void put(UResource.Key key, UResource.Value value, boolean noFallback) {
            assert (key.toString().equals(Constants.CATEGORY_TABLE_NAME));
            assert (value.getType() == UResourceBundle.TABLE);

            UResource.Table categoryTable = value.getTable();
            for (int i = 0; categoryTable.getKeyAndValue(i, key, value); i++) {
                assert (value.getType() == UResourceBundle.STRING);
                mapFromUnitToCategory.put(key.toString(), value.toString());
            }
        }

        public HashMap<String, String> getMapFromUnitToCategory() {
            return mapFromUnitToCategory;
        }
    }
}
