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

import java.text.Format.Field;

import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.MicroProps;
import com.ibm.icu.impl.number.MicroPropsGenerator;
import com.ibm.icu.impl.number.Modifier;
import com.ibm.icu.impl.number.MultiplierProducer;
import com.ibm.icu.impl.number.NumberStringBuilder;
import com.ibm.icu.impl.number.RoundingUtils;
import com.ibm.icu.number.NumberFormatter.SignDisplay;
import com.ibm.icu.number.Precision.SignificantRounderImpl;
import com.ibm.icu.text.DecimalFormatSymbols;
import com.ibm.icu.text.NumberFormat;

/**
 * A class that defines the scientific notation style to be used when formatting numbers in
 * NumberFormatter.
 *
 * <p>
 * To create a ScientificNotation, use one of the factory methods in {@link Notation}.
 *
 * @draft ICU 60
 * @provisional This API might change or be removed in a future release.
 * @see NumberFormatter
 */
public class ScientificNotation extends Notation implements Cloneable {

    int engineeringInterval;
    boolean requireMinInt;
    int minExponentDigits;
    SignDisplay exponentSignDisplay;

    /* package-private */ ScientificNotation(
            int engineeringInterval,
            boolean requireMinInt,
            int minExponentDigits,
            SignDisplay exponentSignDisplay) {
        this.engineeringInterval = engineeringInterval;
        this.requireMinInt = requireMinInt;
        this.minExponentDigits = minExponentDigits;
        this.exponentSignDisplay = exponentSignDisplay;
    }

    /**
     * Sets the minimum number of digits to show in the exponent of scientific notation, padding with
     * zeros if necessary. Useful for fixed-width display.
     *
     * <p>
     * For example, with minExponentDigits=2, the number 123 will be printed as "1.23E02" in
     * <em>en-US</em> instead of the default "1.23E2".
     *
     * @param minExponentDigits
     *            The minimum number of digits to show in the exponent.
     * @return A ScientificNotation, for chaining.
     * @draft ICU 60
     * @provisional This API might change or be removed in a future release.
     * @see NumberFormatter
     */
    public ScientificNotation withMinExponentDigits(int minExponentDigits) {
        if (minExponentDigits >= 1 && minExponentDigits <= RoundingUtils.MAX_INT_FRAC_SIG) {
            ScientificNotation other = (ScientificNotation) this.clone();
            other.minExponentDigits = minExponentDigits;
            return other;
        } else {
            throw new IllegalArgumentException("Integer digits must be between 1 and "
                    + RoundingUtils.MAX_INT_FRAC_SIG
                    + " (inclusive)");
        }
    }

    /**
     * Sets whether to show the sign on positive and negative exponents in scientific notation. The
     * default is AUTO, showing the minus sign but not the plus sign.
     *
     * <p>
     * For example, with exponentSignDisplay=ALWAYS, the number 123 will be printed as "1.23E+2" in
     * <em>en-US</em> instead of the default "1.23E2".
     *
     * @param exponentSignDisplay
     *            The strategy for displaying the sign in the exponent.
     * @return A ScientificNotation, for chaining.
     * @draft ICU 60
     * @provisional This API might change or be removed in a future release.
     * @see NumberFormatter
     */
    public ScientificNotation withExponentSignDisplay(SignDisplay exponentSignDisplay) {
        ScientificNotation other = (ScientificNotation) this.clone();
        other.exponentSignDisplay = exponentSignDisplay;
        return other;
    }

    /**
     * @draft ICU 60
     * @provisional This API might change or be removed in a future release.
     */
    @Override
    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            // Should not happen since parent is Object
            throw new AssertionError(e);
        }
    }

    /* package-private */ MicroPropsGenerator withLocaleData(
            DecimalFormatSymbols symbols,
            boolean build,
            MicroPropsGenerator parent) {
        return new ScientificHandler(this, symbols, build, parent);
    }

    // NOTE: The object lifecycle of ScientificModifier and ScientificHandler differ greatly in Java and
    // C++.
    //
    // During formatting, we need to provide an object with state (the exponent) as the inner modifier.
    //
    // In Java, where the priority is put on reducing object creations, the unsafe code path re-uses the
    // ScientificHandler as a ScientificModifier, and the safe code path pre-computes 25
    // ScientificModifier
    // instances. This scheme reduces the number of object creations by 1 in both safe and unsafe.
    //
    // In C++, MicroProps provides a pre-allocated ScientificModifier, and ScientificHandler simply
    // populates
    // the state (the exponent) into that ScientificModifier. There is no difference between safe and
    // unsafe.

    private static class ScientificHandler implements MicroPropsGenerator, MultiplierProducer, Modifier {

        final ScientificNotation notation;
        final DecimalFormatSymbols symbols;
        final ScientificModifier[] precomputedMods;
        final MicroPropsGenerator parent;
        /* unsafe */ int exponent;

        private ScientificHandler(
                ScientificNotation notation,
                DecimalFormatSymbols symbols,
                boolean safe,
                MicroPropsGenerator parent) {
            this.notation = notation;
            this.symbols = symbols;
            this.parent = parent;

            if (safe) {
                // Pre-build the modifiers for exponents -12 through 12
                precomputedMods = new ScientificModifier[25];
                for (int i = -12; i <= 12; i++) {
                    precomputedMods[i + 12] = new ScientificModifier(i, this);
                }
            } else {
                precomputedMods = null;
            }
        }

        @Override
        public MicroProps processQuantity(DecimalQuantity quantity) {
            MicroProps micros = parent.processQuantity(quantity);
            assert micros.rounder != null;

            // Treat zero as if it had magnitude 0
            int exponent;
            if (quantity.isZero()) {
                if (notation.requireMinInt && micros.rounder instanceof SignificantRounderImpl) {
                    // Show "00.000E0" on pattern "00.000E0"
                    ((SignificantRounderImpl) micros.rounder).apply(quantity,
                            notation.engineeringInterval);
                    exponent = 0;
                } else {
                    micros.rounder.apply(quantity);
                    exponent = 0;
                }
            } else {
                exponent = -micros.rounder.chooseMultiplierAndApply(quantity, this);
            }

            // Add the Modifier for the scientific format.
            if (precomputedMods != null && exponent >= -12 && exponent <= 12) {
                // Safe code path A
                micros.modInner = precomputedMods[exponent + 12];
            } else if (precomputedMods != null) {
                // Safe code path B
                micros.modInner = new ScientificModifier(exponent, this);
            } else {
                // Unsafe code path: mutates the object and re-uses it as a Modifier!
                this.exponent = exponent;
                micros.modInner = this;
            }

            // We already performed rounding. Do not perform it again.
            micros.rounder = Precision.constructPassThrough();

            return micros;
        }

        @Override
        public int getMultiplier(int magnitude) {
            int interval = notation.engineeringInterval;
            int digitsShown;
            if (notation.requireMinInt) {
                // For patterns like "000.00E0" and ".00E0"
                digitsShown = interval;
            } else if (interval <= 1) {
                // For patterns like "0.00E0" and "@@@E0"
                digitsShown = 1;
            } else {
                // For patterns like "##0.00"
                digitsShown = ((magnitude % interval + interval) % interval) + 1;
            }
            return digitsShown - magnitude - 1;
        }

        @Override
        public int getPrefixLength() {
            // TODO: Localized exponent separator location.
            return 0;
        }

        @Override
        public int getCodePointCount() {
            // NOTE: This method is only called one place, NumberRangeFormatterImpl.
            // The call site only cares about != 0 and != 1.
            // Return a very large value so that if this method is used elsewhere, we should notice.
            return 999;
        }

        @Override
        public boolean isStrong() {
            // Scientific is always strong
            return true;
        }

        @Override
        public boolean containsField(Field field) {
            // This method is not currently used. (unsafe path not used in range formatting)
            assert false;
            return false;
        }

        @Override
        public Parameters getParameters() {
            // This method is not currently used.
            assert false;
            return null;
        }

        @Override
        public boolean semanticallyEquivalent(Modifier other) {
            // This method is not currently used. (unsafe path not used in range formatting)
            assert false;
            return false;
        }

        @Override
        public int apply(NumberStringBuilder output, int leftIndex, int rightIndex) {
            return doApply(exponent, output, rightIndex);
        }

        private int doApply(int exponent, NumberStringBuilder output, int rightIndex) {
            // FIXME: Localized exponent separator location.
            int i = rightIndex;
            // Append the exponent separator and sign
            i += output.insert(i, symbols.getExponentSeparator(), NumberFormat.Field.EXPONENT_SYMBOL);
            if (exponent < 0 && notation.exponentSignDisplay != SignDisplay.NEVER) {
                i += output.insert(i, symbols.getMinusSignString(), NumberFormat.Field.EXPONENT_SIGN);
            } else if (exponent >= 0 && notation.exponentSignDisplay == SignDisplay.ALWAYS) {
                i += output.insert(i, symbols.getPlusSignString(), NumberFormat.Field.EXPONENT_SIGN);
            }
            // Append the exponent digits (using a simple inline algorithm)
            int disp = Math.abs(exponent);
            for (int j = 0; j < notation.minExponentDigits || disp > 0; j++, disp /= 10) {
                int d = disp % 10;
                String digitString = symbols.getDigitStringsLocal()[d];
                i += output.insert(i - j, digitString, NumberFormat.Field.EXPONENT);
            }
            return i - rightIndex;
        }
    }

    private static class ScientificModifier implements Modifier {
        final int exponent;
        final ScientificHandler handler;

        ScientificModifier(int exponent, ScientificHandler handler) {
            this.exponent = exponent;
            this.handler = handler;
        }

        @Override
        public int apply(NumberStringBuilder output, int leftIndex, int rightIndex) {
            return handler.doApply(exponent, output, rightIndex);
        }

        @Override
        public int getPrefixLength() {
            // TODO: Localized exponent separator location.
            return 0;
        }

        @Override
        public int getCodePointCount() {
            // NOTE: This method is only called one place, NumberRangeFormatterImpl.
            // The call site only cares about != 0 and != 1.
            // Return a very large value so that if this method is used elsewhere, we should notice.
            return 999;
        }

        @Override
        public boolean isStrong() {
            // Scientific is always strong
            return true;
        }

        @Override
        public boolean containsField(Field field) {
            // This method is not used for inner modifiers.
            assert false;
            return false;
        }

        @Override
        public Parameters getParameters() {
            return null;
        }

        @Override
        public boolean semanticallyEquivalent(Modifier other) {
            if (!(other instanceof ScientificModifier)) {
                return false;
            }
            ScientificModifier _other = (ScientificModifier) other;
            // TODO: Check for locale symbols and settings as well? Could be less efficient.
            return exponent == _other.exponent;
        }
    }
}