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

import com.ibm.icu.util.BytesTrie;
import com.ibm.icu.util.CharsTrie;
import com.ibm.icu.util.CharsTrieBuilder;
import com.ibm.icu.util.ICUCloneNotSupportedException;
import com.ibm.icu.util.MeasureUnit;
import com.ibm.icu.util.StringTrieBuilder;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class MeasureUnitImpl {

    /**
     * The full unit identifier.  Null if not computed.
     */
    private String identifier = null;

    /**
     * The complexity, either SINGLE, COMPOUND, or MIXED.
     */
    private MeasureUnit.Complexity complexity = MeasureUnit.Complexity.SINGLE;

    /**
     * The list of simple units. These may be summed or multiplied, based on the
     * value of the complexity field.
     * <p>
     * The "dimensionless" unit (SingleUnitImpl default constructor) must not be
     * added to this list.
     * <p>
     * The "dimensionless" <code>MeasureUnitImpl</code> has an empty <code>singleUnits</code>.
     */
    private ArrayList<SingleUnitImpl> singleUnits;

    public MeasureUnitImpl() {
        singleUnits = new ArrayList<>();
    }

    public MeasureUnitImpl(SingleUnitImpl singleUnit) {
        this();
        this.appendSingleUnit(singleUnit);
    }

    /**
     * Parse a unit identifier into a MeasureUnitImpl.
     *
     * @param identifier The unit identifier string.
     * @return A newly parsed object.
     * @throws <code>IllegalArgumentException</code> in case of incorrect/non-parsed identifier.
     */
    public static MeasureUnitImpl forIdentifier(String identifier) {
        return UnitsParser.parseForIdentifier(identifier);
    }

    /**
     * Used for currency units.
     */
    public static MeasureUnitImpl forCurrencyCode(String currencyCode) {
        MeasureUnitImpl result = new MeasureUnitImpl();
        result.identifier = currencyCode;
        return result;
    }

    public MeasureUnitImpl clone() {
        MeasureUnitImpl result = new MeasureUnitImpl();
        result.complexity = this.complexity;
        result.identifier = this.identifier;
        result.singleUnits = (ArrayList<SingleUnitImpl>) this.singleUnits.clone();
        return result;
    }

    /**
     * Returns the list of simple units.
     */
    public ArrayList<SingleUnitImpl> getSingleUnits() {
        return singleUnits;
    }

    /**
     * Mutates this MeasureUnitImpl to take the reciprocal.
     */
    public void takeReciprocal() {
        this.identifier = null;
        for (SingleUnitImpl singleUnit :
                this.singleUnits) {
            singleUnit.setDimensionality(singleUnit.getDimensionality() * -1);
        }
    }

    /**
     * Extracts the list of all the individual units inside the `MeasureUnitImpl`.
     * For example:
     * -   if the <code>MeasureUnitImpl</code> is <code>foot-per-hour</code>
     * it will return a list of 1 <code>{foot-per-hour}</code>
     * -   if the <code>MeasureUnitImpl</code> is <code>foot-and-inch</code>
     * it will return a list of 2 <code>{ foot, inch}</code>
     *
     * @return a list of <code>MeasureUnitImpl</code>
     */
    public ArrayList<MeasureUnitImpl> extractIndividualUnits() {
        ArrayList<MeasureUnitImpl> result = new ArrayList<MeasureUnitImpl>();
        if (this.getComplexity() == MeasureUnit.Complexity.MIXED) {
            // In case of mixed units, each single unit can be considered as a stand alone MeasureUnitImpl.
            for (SingleUnitImpl singleUnit :
                    this.getSingleUnits()) {
                result.add(new MeasureUnitImpl(singleUnit));
            }

            return result;
        }

        result.add(this.clone());
        return result;
    }

    /**
     * Applies dimensionality to all the internal single units.
     * For example: <b>square-meter-per-second</b>, when we apply dimensionality -2, it will be <b>square-second-per-p4-meter</b>
     */
    public void applyDimensionality(int dimensionality) {
        for (SingleUnitImpl singleUnit :
                singleUnits) {
            singleUnit.setDimensionality(singleUnit.getDimensionality() * dimensionality);
        }
    }

    /**
     * Mutates this MeasureUnitImpl to append a single unit.
     *
     * @return true if a new item was added. If unit is the dimensionless unit,
     * it is never added: the return value will always be false.
     */
    public boolean appendSingleUnit(SingleUnitImpl singleUnit) {
        identifier = null;

        if (singleUnit == null) {
            // We don't append dimensionless units.
            return false;
        }

        // Find a similar unit that already exists, to attempt to coalesce
        SingleUnitImpl oldUnit = null;
        for (int i = 0, n = this.singleUnits.size(); i < n; i++) {
            SingleUnitImpl candidate = this.singleUnits.get(i);
            if (candidate.isCompatibleWith(singleUnit)) {
                oldUnit = candidate;
                break;
            }
        }

        if (oldUnit != null) {
            // Both dimensionalities will be positive, or both will be negative, by
            // virtue of isCompatibleWith().
            oldUnit.setDimensionality(oldUnit.getDimensionality() + singleUnit.getDimensionality());

            return false;
        }

        // Add a copy of singleUnit
        this.singleUnits.add(singleUnit.clone());

        // If the MeasureUnitImpl is `UMEASURE_UNIT_SINGLE` and after the appending a unit, the singleUnits are more
        // than one singleUnit. thus means the complexity should be `UMEASURE_UNIT_COMPOUND`
        if (this.singleUnits.size() > 1 && this.complexity == MeasureUnit.Complexity.SINGLE) {
            this.setComplexity(MeasureUnit.Complexity.COMPOUND);
        }

        return true;
    }

    /**
     * Transform this MeasureUnitImpl into a MeasureUnit, simplifying if possible.
     * <p>
     * NOTE: this function must be called from a thread-safe class
     */
    public MeasureUnit build() {
        return MeasureUnit.fromMeasureUnitImpl(this);
    }

    /**
     * @return SingleUnitImpl
     * @throws UnsupportedOperationException if the object could not be converted to SingleUnitImpl.
     */
    public SingleUnitImpl getSingleUnitImpl() {
        if (this.singleUnits.size() == 0) {
            return new SingleUnitImpl();
        }
        if (this.singleUnits.size() == 1) {
            return this.singleUnits.get(0).clone();
        }

        throw new UnsupportedOperationException();
    }


    /**
     * Returns the CLDR unit identifier and null if not computed.
     */
    public String getIdentifier() {
        return identifier;
    }

    public MeasureUnit.Complexity getComplexity() {
        return complexity;
    }

    public void setComplexity(MeasureUnit.Complexity complexity) {
        this.complexity = complexity;
    }

    /**
     * Normalizes the MeasureUnitImpl and generates the identifier string in place.
     */
    public void serialize() {
        if (this.getSingleUnits().size() == 0) {
            // Dimensionless, constructed by the default constructor: no appending
            // to this.result, we wish it to contain the zero-length string.
            return;
        }
        if (this.complexity == MeasureUnit.Complexity.COMPOUND) {
            // Note: don't sort a MIXED unit
            Collections.sort(this.getSingleUnits(), new SingleUnitComparator());
        }

        StringBuilder result = new StringBuilder();
        boolean beforePer = true;
        boolean firstTimeNegativeDimension = false;
        for (SingleUnitImpl singleUnit :
                this.getSingleUnits()) {
            if (beforePer && singleUnit.getDimensionality() < 0) {
                beforePer = false;
                firstTimeNegativeDimension = true;
            } else if (singleUnit.getDimensionality() < 0) {
                firstTimeNegativeDimension = false;
            }

            String singleUnitIdentifier = singleUnit.getNeutralIdentifier();
            if (this.getComplexity() == MeasureUnit.Complexity.MIXED) {
                if (result.length() != 0) {
                    result.append("-and-");
                }
            } else {
                if (firstTimeNegativeDimension) {
                    if (result.length() == 0) {
                        result.append("per-");
                    } else {
                        result.append("-per-");
                    }
                } else {
                    if (result.length() != 0) {
                        result.append("-");
                    }
                }
            }

            result.append(singleUnitIdentifier);
        }

        this.identifier = result.toString();
    }

    public enum CompoundPart {
        // Represents "-per-"
        PER(0),
        // Represents "-"
        TIMES(1),
        // Represents "-and-"
        AND(2);

        private final int index;

        CompoundPart(int index) {
            this.index = index;
        }

        public static CompoundPart getCompoundPartFromTrieIndex(int trieIndex) {
            int index = trieIndex - UnitsData.Constants.kCompoundPartOffset;
            switch (index) {
                case 0:
                    return CompoundPart.PER;
                case 1:
                    return CompoundPart.TIMES;
                case 2:
                    return CompoundPart.AND;
                default:
                    throw new AssertionError("CompoundPart index must be 0, 1 or 2");
            }
        }

        public int getTrieIndex() {
            return this.index + UnitsData.Constants.kCompoundPartOffset;
        }

        public int getValue() {
            return index;
        }
    }

    public enum PowerPart {
        P2(2),
        P3(3),
        P4(4),
        P5(5),
        P6(6),
        P7(7),
        P8(8),
        P9(9),
        P10(10),
        P11(11),
        P12(12),
        P13(13),
        P14(14),
        P15(15);

        private final int power;

        PowerPart(int power) {
            this.power = power;
        }

        public static int getPowerFromTrieIndex(int trieIndex) {
            return trieIndex - UnitsData.Constants.kPowerPartOffset;
        }

        public int getTrieIndex() {
            return this.power + UnitsData.Constants.kPowerPartOffset;
        }

        public int getValue() {
            return power;
        }
    }

    public enum InitialCompoundPart {

        // Represents "per-", the only compound part that can appear at the start of
        // an identifier.
        INITIAL_COMPOUND_PART_PER(0);

        private final int index;

        InitialCompoundPart(int powerIndex) {
            this.index = powerIndex;
        }

        public static InitialCompoundPart getInitialCompoundPartFromTrieIndex(int trieIndex) {
            int index = trieIndex - UnitsData.Constants.kInitialCompoundPartOffset;
            if (index == 0) {
                return INITIAL_COMPOUND_PART_PER;
            }

            throw new IllegalArgumentException("Incorrect trieIndex");
        }

        public int getTrieIndex() {
            return this.index + UnitsData.Constants.kInitialCompoundPartOffset;
        }

        public int getValue() {
            return index;
        }

    }

    public static class UnitsParser {
        // This used only to not build the trie each time we use the parser
        private volatile static CharsTrie savedTrie = null;
        private final String[] simpleUnits;
        // This trie used in the parsing operation.
        private CharsTrie trie;
        // Tracks parser progress: the offset into fSource.
        private int fIndex = 0;
        // Set to true when we've seen a "-per-" or a "per-", after which all units
        // are in the denominator. Until we find an "-and-", at which point the
        // identifier is invalid pending TODO(CLDR-13700).
        private boolean fAfterPer = false;
        private String fSource;
        // If an "-and-" was parsed prior to finding the "single
        //     * unit", sawAnd is set to true. If not, it is left as is.
        private boolean fSawAnd = false;

        private UnitsParser(String identifier) {
            this.simpleUnits = UnitsData.getSimpleUnits();
            this.fSource = identifier;

            if (UnitsParser.savedTrie != null) {
                try {
                    this.trie = UnitsParser.savedTrie.clone();
                } catch (CloneNotSupportedException e) {
                    throw new ICUCloneNotSupportedException();
                }
                return;
            }

            // Building the trie.
            CharsTrieBuilder trieBuilder;
            trieBuilder = new CharsTrieBuilder();

            // Add syntax parts (compound, power prefixes)
            trieBuilder.add("-per-", CompoundPart.PER.getTrieIndex());
            trieBuilder.add("-", CompoundPart.TIMES.getTrieIndex());
            trieBuilder.add("-and-", CompoundPart.AND.getTrieIndex());
            trieBuilder.add("per-", InitialCompoundPart.INITIAL_COMPOUND_PART_PER.getTrieIndex());
            trieBuilder.add("square-", PowerPart.P2.getTrieIndex());
            trieBuilder.add("cubic-", PowerPart.P3.getTrieIndex());
            trieBuilder.add("pow2-", PowerPart.P2.getTrieIndex());
            trieBuilder.add("pow3-", PowerPart.P3.getTrieIndex());
            trieBuilder.add("pow4-", PowerPart.P4.getTrieIndex());
            trieBuilder.add("pow5-", PowerPart.P5.getTrieIndex());
            trieBuilder.add("pow6-", PowerPart.P6.getTrieIndex());
            trieBuilder.add("pow7-", PowerPart.P7.getTrieIndex());
            trieBuilder.add("pow8-", PowerPart.P8.getTrieIndex());
            trieBuilder.add("pow9-", PowerPart.P9.getTrieIndex());
            trieBuilder.add("pow10-", PowerPart.P10.getTrieIndex());
            trieBuilder.add("pow11-", PowerPart.P11.getTrieIndex());
            trieBuilder.add("pow12-", PowerPart.P12.getTrieIndex());
            trieBuilder.add("pow13-", PowerPart.P13.getTrieIndex());
            trieBuilder.add("pow14-", PowerPart.P14.getTrieIndex());
            trieBuilder.add("pow15-", PowerPart.P15.getTrieIndex());

            // Add SI prefixes
            for (MeasureUnit.SIPrefix siPrefix :
                    MeasureUnit.SIPrefix.values()) {
                trieBuilder.add(siPrefix.getIdentifier(), getTrieIndex(siPrefix));
            }

            // Add simple units
            for (int i = 0; i < simpleUnits.length; i++) {
                trieBuilder.add(simpleUnits[i], i + UnitsData.Constants.kSimpleUnitOffset);

            }

            // TODO: Use SLOW or FAST here?
            UnitsParser.savedTrie = trieBuilder.build(StringTrieBuilder.Option.FAST);

            try {
                this.trie = UnitsParser.savedTrie.clone();
            } catch (CloneNotSupportedException e) {
                throw new ICUCloneNotSupportedException();
            }
        }


        /**
         * Construct a MeasureUnit from a CLDR Unit Identifier, defined in UTS 35.
         * Validates and canonicalizes the identifier.
         *
         * @return MeasureUnitImpl object or null if the identifier is empty.
         * @throws IllegalArgumentException in case of invalid identifier.
         */
        public static MeasureUnitImpl parseForIdentifier(String identifier) {
            if (identifier == null || identifier.isEmpty()) {
                return null;
            }

            UnitsParser parser = new UnitsParser(identifier);
            return parser.parse();

        }

        private static MeasureUnit.SIPrefix getSiPrefixFromTrieIndex(int trieIndex) {
            for (MeasureUnit.SIPrefix element :
                    MeasureUnit.SIPrefix.values()) {
                if (getTrieIndex(element) == trieIndex)
                    return element;
            }

            throw new IllegalArgumentException("Incorrect trieIndex");
        }

        private static int getTrieIndex(MeasureUnit.SIPrefix prefix) {
            return prefix.getSiPrefixPower() + UnitsData.Constants.kSIPrefixOffset;
        }

        private MeasureUnitImpl parse() {
            MeasureUnitImpl result = new MeasureUnitImpl();

            if (fSource.isEmpty()) {
                // The dimensionless unit: nothing to parse. return null.
                return null;
            }

            while (hasNext()) {
                fSawAnd = false;
                SingleUnitImpl singleUnit = nextSingleUnit();

                boolean added = result.appendSingleUnit(singleUnit);
                if (fSawAnd && !added) {
                    throw new IllegalArgumentException("Two similar units are not allowed in a mixed unit.");
                }

                if ((result.singleUnits.size()) >= 2) {
                    // nextSingleUnit fails appropriately for "per" and "and" in the
                    // same identifier. It doesn't fail for other compound units
                    // (COMPOUND_PART_TIMES). Consequently we take care of that
                    // here.
                    MeasureUnit.Complexity complexity =
                            fSawAnd ? MeasureUnit.Complexity.MIXED : MeasureUnit.Complexity.COMPOUND;
                    if (result.getSingleUnits().size() == 2) {
                        // After appending two singleUnits, the complexity will be `UMEASURE_UNIT_COMPOUND`
                        assert result.getComplexity() == MeasureUnit.Complexity.COMPOUND;
                        result.setComplexity(complexity);
                    } else if (result.getComplexity() != complexity) {
                        throw new IllegalArgumentException("Can't have mixed compound units");
                    }
                }
            }

            return result;
        }

        /**
         * Returns the next "single unit" via result.
         * <p>
         * If a "-per-" was parsed, the result will have appropriate negative
         * dimensionality.
         * <p>
         *
         * @throws IllegalArgumentException if we parse both compound units and "-and-", since mixed
         *                                  compound units are not yet supported - TODO(CLDR-13700).
         */
        private SingleUnitImpl nextSingleUnit() {
            SingleUnitImpl result = new SingleUnitImpl();

            // state:
            // 0 = no tokens seen yet (will accept power, SI prefix, or simple unit)
            // 1 = power token seen (will not accept another power token)
            // 2 = SI prefix token seen (will not accept a power or SI prefix token)
            int state = 0;

            boolean atStart = fIndex == 0;
            Token token = nextToken();

            if (atStart) {
                // Identifiers optionally start with "per-".
                if (token.getType() == Token.Type.TYPE_INITIAL_COMPOUND_PART) {
                    assert token.getInitialCompoundPart() == InitialCompoundPart.INITIAL_COMPOUND_PART_PER;

                    fAfterPer = true;
                    result.setDimensionality(-1);

                    token = nextToken();
                }
            } else {
                // All other SingleUnit's are separated from previous SingleUnit's
                // via a compound part:
                if (token.getType() != Token.Type.TYPE_COMPOUND_PART) {
                    throw new IllegalArgumentException("token type must be TYPE_COMPOUND_PART");
                }

                CompoundPart compoundPart = CompoundPart.getCompoundPartFromTrieIndex(token.getMatch());
                switch (compoundPart) {
                    case PER:
                        if (fSawAnd) {
                            throw new IllegalArgumentException("Mixed compound units not yet supported");
                            // TODO(CLDR-13700).
                        }

                        fAfterPer = true;
                        result.setDimensionality(-1);
                        break;

                    case TIMES:
                        if (fAfterPer) {
                            result.setDimensionality(-1);
                        }
                        break;

                    case AND:
                        if (fAfterPer) {
                            // not yet supported, TODO(CLDR-13700).
                            throw new IllegalArgumentException("Can't start with \"-and-\", and mixed compound units");
                        }
                        fSawAnd = true;
                        break;
                }

                token = nextToken();
            }

            // Read tokens until we have a complete SingleUnit or we reach the end.
            while (true) {
                switch (token.getType()) {
                    case TYPE_POWER_PART:
                        if (state > 0) {
                            throw new IllegalArgumentException();
                        }

                        result.setDimensionality(result.getDimensionality() * token.getPower());
                        state = 1;
                        break;

                    case TYPE_SI_PREFIX:
                        if (state > 1) {
                            throw new IllegalArgumentException();
                        }

                        result.setSiPrefix(token.getSIPrefix());
                        state = 2;
                        break;

                    case TYPE_SIMPLE_UNIT:
                        result.setSimpleUnit(token.getSimpleUnitIndex(), simpleUnits);
                        return result;

                    default:
                        throw new IllegalArgumentException();
                }

                if (!hasNext()) {
                    throw new IllegalArgumentException("We ran out of tokens before finding a complete single unit.");
                }

                token = nextToken();
            }
        }

        private boolean hasNext() {
            return fIndex < fSource.length();
        }

        private Token nextToken() {
            trie.reset();
            int match = -1;
            // Saves the position in the fSource string for the end of the most
            // recent matching token.
            int previ = -1;

            // Find the longest token that matches a value in the trie:
            while (fIndex < fSource.length()) {
                BytesTrie.Result result = trie.next(fSource.charAt(fIndex++));
                if (result == BytesTrie.Result.NO_MATCH) {
                    break;
                } else if (result == BytesTrie.Result.NO_VALUE) {
                    continue;
                }

                match = trie.getValue();
                previ = fIndex;

                if (result == BytesTrie.Result.FINAL_VALUE) {
                    break;
                }

                if (result != BytesTrie.Result.INTERMEDIATE_VALUE) {
                    throw new IllegalArgumentException("result must has an intermediate value");
                }

                // continue;
            }


            if (match < 0) {
                throw new IllegalArgumentException("Encountered unknown token starting at index " + previ);
            } else {
                fIndex = previ;
            }

            return new Token(match);
        }

        static class Token {

            private final int fMatch;
            private final Type type;

            public Token(int fMatch) {
                this.fMatch = fMatch;
                type = calculateType(fMatch);
            }

            public Type getType() {
                return this.type;
            }

            public MeasureUnit.SIPrefix getSIPrefix() {
                assert this.type == Type.TYPE_SI_PREFIX;
                return getSiPrefixFromTrieIndex(this.fMatch);
            }

            // Valid only for tokens with type TYPE_COMPOUND_PART.
            public int getMatch() {
                assert getType() == Type.TYPE_COMPOUND_PART;
                return fMatch;
            }

            // Even if there is only one InitialCompoundPart value, we have this
            // function for the simplicity of code consistency.
            public InitialCompoundPart getInitialCompoundPart() {
                assert (this.type == Type.TYPE_INITIAL_COMPOUND_PART
                        &&
                        fMatch == InitialCompoundPart.INITIAL_COMPOUND_PART_PER.getTrieIndex());
                return InitialCompoundPart.getInitialCompoundPartFromTrieIndex(fMatch);
            }

            public int getPower() {
                assert this.type == Type.TYPE_POWER_PART;
                return PowerPart.getPowerFromTrieIndex(this.fMatch);
            }

            public int getSimpleUnitIndex() {
                return this.fMatch - UnitsData.Constants.kSimpleUnitOffset;
            }

            // Calling calculateType() is invalid, resulting in an assertion failure, if Token
            // value isn't positive.
            private Type calculateType(int fMatch) {
                if (fMatch <= 0) {
                    throw new AssertionError("fMatch must have a positive value");
                }

                if (fMatch < UnitsData.Constants.kCompoundPartOffset) {
                    return Type.TYPE_SI_PREFIX;
                }
                if (fMatch < UnitsData.Constants.kInitialCompoundPartOffset) {
                    return Type.TYPE_COMPOUND_PART;
                }
                if (fMatch < UnitsData.Constants.kPowerPartOffset) {
                    return Type.TYPE_INITIAL_COMPOUND_PART;
                }
                if (fMatch < UnitsData.Constants.kSimpleUnitOffset) {
                    return Type.TYPE_POWER_PART;
                }

                return Type.TYPE_SIMPLE_UNIT;
            }

            enum Type {
                TYPE_UNDEFINED,
                TYPE_SI_PREFIX,
                // Token type for "-per-", "-", and "-and-".
                TYPE_COMPOUND_PART,
                // Token type for "per-".
                TYPE_INITIAL_COMPOUND_PART,
                TYPE_POWER_PART,
                TYPE_SIMPLE_UNIT,
            }
        }
    }

    static class MeasureUnitImplComparator implements Comparator<MeasureUnitImpl> {
        private ConversionRates conversionRates;

        public MeasureUnitImplComparator(ConversionRates conversionRates) {
            this.conversionRates = conversionRates;
        }

        @Override
        public int compare(MeasureUnitImpl o1, MeasureUnitImpl o2) {
            UnitConverter fromO1toO2 = new UnitConverter(o1, o2, conversionRates);
            return fromO1toO2.convert(BigDecimal.valueOf(1)).compareTo(BigDecimal.valueOf(1));
        }
    }

    static class SingleUnitComparator implements Comparator<SingleUnitImpl> {
        @Override
        public int compare(SingleUnitImpl o1, SingleUnitImpl o2) {
            return o1.compareTo(o2);
        }
    }

    @Override
    public String toString() {
        return "MeasureUnitImpl [" + build().getIdentifier() + "]";
    }
}
