// © 2020 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
package com.ibm.icu.impl.number;

import java.util.ArrayList;
import java.util.List;

import com.ibm.icu.impl.FormattedStringBuilder;
import com.ibm.icu.impl.SimpleFormatterImpl;
import com.ibm.icu.impl.StandardPlural;
import com.ibm.icu.number.LocalizedNumberFormatter;
import com.ibm.icu.number.NumberFormatter;
import com.ibm.icu.text.ListFormatter;
import com.ibm.icu.text.PluralRules;
import com.ibm.icu.text.SimpleFormatter;
import com.ibm.icu.util.MeasureUnit;
import com.ibm.icu.util.ULocale;

/** Similar to LongNameHandler, but only for MIXED units. */
public class MixedUnitLongNameHandler
    implements MicroPropsGenerator, ModifierStore, LongNameMultiplexer.ParentlessMicroPropsGenerator {
    private final PluralRules rules;
    private final MicroPropsGenerator parent;

    /**
     * Stores unit data for each of the individual units. For each unit, it
     * stores ARRAY_LENGTH strings, as returned by getMeasureData.
     */
    private List<String[]> fMixedUnitData;

    /**
     * A localized NumberFormatter used to format the integer-valued bigger
     * units of Mixed Unit measurements.
     */
    private LocalizedNumberFormatter fIntegerFormatter;

    /** A localised list formatter for joining mixed units together. */
    private ListFormatter fListFormatter;

    private MixedUnitLongNameHandler(PluralRules rules, MicroPropsGenerator parent) {
        this.rules = rules;
        this.parent = parent;
    }

    /**
     * Construct a localized MixedUnitLongNameHandler for the specified
     * MeasureUnit. It must be a MIXED unit.
     * <p>
     *
     * @param locale    The desired locale.
     * @param mixedUnit The mixed measure unit to construct a
     *                  MixedUnitLongNameHandler for.
     * @param width     Specifies the desired unit rendering.
     * @param unitDisplayName
     * @param rules     PluralRules instance.
     * @param parent    MicroPropsGenerator instance.
     */
    public static MixedUnitLongNameHandler forMeasureUnit(ULocale locale,
                                                          MeasureUnit mixedUnit,
                                                          NumberFormatter.UnitWidth width,
                                                          String unitDisplayName,
                                                          PluralRules rules,
                                                          MicroPropsGenerator parent) {
        assert (mixedUnit.getComplexity() == MeasureUnit.Complexity.MIXED);

        MixedUnitLongNameHandler result = new MixedUnitLongNameHandler(rules, parent);
        List<MeasureUnit> individualUnits = mixedUnit.splitToSingleUnits();

        result.fMixedUnitData = new ArrayList<>();
        for (int i = 0; i < individualUnits.size(); i++) {
            // Grab data for each of the components.
            String[] unitData = new String[LongNameHandler.ARRAY_LENGTH];
            LongNameHandler.getMeasureData(locale, individualUnits.get(i), width, unitDisplayName, unitData);
            result.fMixedUnitData.add(unitData);
        }

        ListFormatter.Width listWidth = ListFormatter.Width.SHORT;
        if (width == NumberFormatter.UnitWidth.NARROW) {
            listWidth = ListFormatter.Width.NARROW;
        } else if (width == NumberFormatter.UnitWidth.FULL_NAME) {
            // This might be the same as SHORT in most languages:
            listWidth = ListFormatter.Width.WIDE;
        }

        result.fListFormatter = ListFormatter.getInstance(locale, ListFormatter.Type.UNITS, listWidth);


        // We need a localised NumberFormatter for the integers of the bigger units
        // (providing Arabic numerals, for example).
        result.fIntegerFormatter = NumberFormatter.withLocale(locale);

        return result;
    }

    /**
     * Produces a plural-appropriate Modifier for a mixed unit: `quantity` is
     * taken as the final smallest unit, while the larger unit values must be
     * provided by `micros.mixedMeasures`, micros being the MicroProps instance
     * returned by the parent.
     *
     * This function must not be called if this instance has no parent: call
     * processQuantityWithMicros() instead.
     */
    @Override
    public MicroProps processQuantity(DecimalQuantity quantity) {
        assert (fMixedUnitData.size() > 1);
        MicroProps micros;
        micros = parent.processQuantity(quantity);
        micros.modOuter = getMixedUnitModifier(quantity, micros);
        return micros;
    }

    /**
     * Produces a plural-appropriate Modifier for a mixed unit: `quantity` is
     * taken as the final smallest unit, while the larger unit values must be
     * provided via `micros.mixedMeasures`.
     *
     * Does not call parent.processQuantity, so cannot get a MicroProps instance
     * that way. Instead, the instance is passed in as a parameter.
     */
    public MicroProps processQuantityWithMicros(DecimalQuantity quantity, MicroProps micros) {
        assert (fMixedUnitData.size() > 1);
        micros.modOuter = getMixedUnitModifier(quantity, micros);
        return micros;
    }

    /**
     * Required for ModifierStore. And ModifierStore is required by
     * SimpleModifier constructor's last parameter. We assert his will never get
     * called though.
     */
    @Override
    public Modifier getModifier(Modifier.Signum signum, StandardPlural plural) {
        // TODO(units): investigate this method while investigating where
        // LongNameHandler.getModifier() gets used. To be sure it remains
        // unreachable:
        assert false : "should be unreachable";
        return null;
    }

    /**
     * For a mixed unit, returns a Modifier that takes only one parameter: the
     * smallest and final unit of the set. The bigger units' values and labels
     * get baked into this Modifier, together with the unit label of the final
     * unit.
     */
    private Modifier getMixedUnitModifier(DecimalQuantity quantity, MicroProps micros) {
        // If we don't have at least one mixedMeasure, the LongNameHandler would be
        // sufficient and we shouldn't be running MixedUnitLongNameHandler code:
        if (micros.mixedMeasures.size() == 0) {
            assert false : "Mixed unit: we must have more than one unit value";
            throw new UnsupportedOperationException();
        }

        // Algorithm:
        //
        // For the mixed-units measurement of: "3 yard, 1 foot, 2.6 inch", we should
        // find "3 yard" and "1 foot" in micros.mixedMeasures.
        //
        // Obtain long-names with plural forms corresponding to measure values:
        //   * {0} yards, {0} foot, {0} inches
        //
        // Format the integer values appropriately and modify with the format
        // strings:
        //   - 3 yards, 1 foot
        //
        // Use ListFormatter to combine, with one placeholder:
        //   - 3 yards, 1 foot and {0} inches /* TODO: how about the case of `1 inch` */
        //
        // Return a SimpleModifier for this pattern, letting the rest of the
        // pipeline take care of the remaining inches.

        List<String> outputMeasuresList = new ArrayList<>();

        StandardPlural quantityPlural = StandardPlural.OTHER;
        for (int i = 0; i < micros.mixedMeasures.size(); i++) {

            if ( i  == micros.indexOfQuantity) {
                if (i > 0 && quantity.isNegative()) {
                    // If numbers are negative, only the first number needs to have its
                    // negative sign formatted.
                    quantity.negate();
                }

                quantityPlural = RoundingUtils.getPluralSafe(micros.rounder, rules, quantity);
                String quantitySimpleFormat = LongNameHandler.getWithPlural(this.fMixedUnitData.get(i), quantityPlural);
                SimpleFormatter finalFormatter = SimpleFormatter.compileMinMaxArguments(quantitySimpleFormat, 0, 1);
                outputMeasuresList.add(finalFormatter.format("{0}"));

                continue;
            }


            DecimalQuantity fdec = new DecimalQuantity_DualStorageBCD(micros.mixedMeasures.get(i).getNumber());
            if (i > 0 && fdec.isNegative()) {
                // If numbers are negative, only the first number needs to have its
                // negative sign formatted.
                fdec.negate();
            }

            StandardPlural pluralForm = RoundingUtils.getPluralSafe(micros.rounder, rules, fdec);

            String simpleFormat = LongNameHandler.getWithPlural(this.fMixedUnitData.get(i), pluralForm);
            SimpleFormatter compiledFormatter = SimpleFormatter.compileMinMaxArguments(simpleFormat, 0, 1);

            FormattedStringBuilder appendable = new FormattedStringBuilder();
            this.fIntegerFormatter.formatImpl(fdec, appendable);
            outputMeasuresList.add(compiledFormatter.format(appendable.toString()));
            // TODO(icu-units#67): fix field positions
        }


        // Combine list into a "premixed" pattern
        String premixedFormatPattern = this.fListFormatter.format(outputMeasuresList);
        StringBuilder sb = new StringBuilder();
        String premixedCompiled =
            SimpleFormatterImpl.compileToStringMinMaxArguments(premixedFormatPattern, sb, 0, 1);

        // TODO(icu-units#67): fix field positions
        Modifier.Parameters params = new Modifier.Parameters();
        params.obj = this;
        params.signum = Modifier.Signum.POS_ZERO;
        params.plural = quantityPlural;
        // Return a SimpleModifier for the "premixed" pattern
        return new SimpleModifier(premixedCompiled, null, false, params);
    }
}
