// © 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.MeasureUnit;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.regex.Pattern;

import static java.math.MathContext.DECIMAL128;

public class UnitConverter {
    private BigDecimal conversionRate;
    private BigDecimal offset;

    /**
     * Constructor of `UnitConverter`.
     * NOTE:
     * - source and target must be under the same category
     * - e.g. meter to mile --> both of them are length units.
     *
     * @param source          represents the source unit.
     * @param target          represents the target unit.
     * @param conversionRates contains all the needed conversion rates.
     */
    public UnitConverter(MeasureUnitImpl source, MeasureUnitImpl target, ConversionRates conversionRates) {
        Convertibility convertibility = extractConvertibility(source, target, conversionRates);
        assert (convertibility == Convertibility.CONVERTIBLE || convertibility == Convertibility.RECIPROCAL);

        Factor sourceToBase = conversionRates.getFactorToBase(source);
        Factor targetToBase = conversionRates.getFactorToBase(target);

        if (convertibility == Convertibility.CONVERTIBLE) {
            this.conversionRate = sourceToBase.divide(targetToBase).getConversionRate();
        } else {
            this.conversionRate = sourceToBase.multiply(targetToBase).getConversionRate();
        }

        // calculate the offset
        this.offset = conversionRates.getOffset(source, target, sourceToBase, targetToBase, convertibility);
    }

    static public Convertibility extractConvertibility(MeasureUnitImpl source, MeasureUnitImpl target, ConversionRates conversionRates) {
        ArrayList<SingleUnitImpl> sourceSingleUnits = conversionRates.extractBaseUnits(source);
        ArrayList<SingleUnitImpl> targetSingleUnits = conversionRates.extractBaseUnits(target);

        HashMap<String, Integer> dimensionMap = new HashMap<>();

        insertInMap(dimensionMap, sourceSingleUnits, 1);
        insertInMap(dimensionMap, targetSingleUnits, -1);

        if (areDimensionsZeroes(dimensionMap)) return Convertibility.CONVERTIBLE;

        insertInMap(dimensionMap, targetSingleUnits, 2);
        if (areDimensionsZeroes(dimensionMap)) return Convertibility.RECIPROCAL;

        return Convertibility.UNCONVERTIBLE;
    }

    /**
     * Helpers
     */
    private static void insertInMap(HashMap<String, Integer> dimensionMap, ArrayList<SingleUnitImpl> singleUnits, int multiplier) {
        for (SingleUnitImpl singleUnit :
                singleUnits) {
            if (dimensionMap.containsKey(singleUnit.getSimpleUnit())) {
                dimensionMap.put(singleUnit.getSimpleUnit(), dimensionMap.get(singleUnit.getSimpleUnit()) + singleUnit.getDimensionality() * multiplier);
            } else {
                dimensionMap.put(singleUnit.getSimpleUnit(), singleUnit.getDimensionality() * multiplier);
            }
        }
    }

    private static boolean areDimensionsZeroes(HashMap<String, Integer> dimensionMap) {
        for (Integer value :
                dimensionMap.values()) {
            if (!value.equals(0)) return false;
        }

        return true;
    }

    public BigDecimal convert(BigDecimal inputValue) {
        return inputValue.multiply(this.conversionRate).add(offset);
    }

    public enum Convertibility {
        CONVERTIBLE,
        RECIPROCAL,
        UNCONVERTIBLE,
    }

    // TODO: improve documentation and Constant implementation

    /**
     * Responsible for all the Factor operation
     * NOTE:
     * This class is immutable
     */
    static class Factor {
        private BigDecimal factorNum;
        private BigDecimal factorDen;
        /* FACTOR CONSTANTS */
        private int
                CONSTANT_FT2M = 0,    // ft2m stands for foot to meter.
                CONSTANT_PI = 0,      // PI
                CONSTANT_GRAVITY = 0, // Gravity
                CONSTANT_G = 0,
                CONSTANT_GAL_IMP2M3 = 0, // Gallon imp to m3
                CONSTANT_LB2KG = 0;      // Pound to Kilogram


        /**
         * Creates Empty Factor
         */
        public Factor() {
            this.factorNum = BigDecimal.valueOf(1);
            this.factorDen = BigDecimal.valueOf(1);
        }

        public static Factor processFactor(String factor) {
            assert (!factor.isEmpty());

            // Remove all spaces in the factor
            factor.replaceAll("\\s+", "");

            String[] fractions = factor.split("/");
            assert (fractions.length == 1 || fractions.length == 2);

            if (fractions.length == 1) {
                return processFactorWithoutDivision(fractions[0]);
            }

            Factor num = processFactorWithoutDivision(fractions[0]);
            Factor den = processFactorWithoutDivision(fractions[1]);
            return num.divide(den);
        }

        private static Factor processFactorWithoutDivision(String factorWithoutDivision) {
            Factor result = new Factor();
            for (String poweredEntity :
                    factorWithoutDivision.split(Pattern.quote("*"))) {
                result.addPoweredEntity(poweredEntity);
            }

            return result;
        }

        /**
         * Clone this <code>Factor</code>.
         */
        protected Factor clone() {
            Factor result = new Factor();
            result.factorNum = this.factorNum;
            result.factorDen = this.factorDen;

            result.CONSTANT_FT2M = this.CONSTANT_FT2M;
            result.CONSTANT_PI = this.CONSTANT_PI;
            result.CONSTANT_GRAVITY = this.CONSTANT_GRAVITY;
            result.CONSTANT_G = this.CONSTANT_G;
            result.CONSTANT_GAL_IMP2M3 = this.CONSTANT_GAL_IMP2M3;
            result.CONSTANT_LB2KG = this.CONSTANT_LB2KG;

            return result;
        }

        /**
         * Returns a single `BigDecimal` that represent the conversion rate after substituting all the constants.
         *
         * @return
         */
        public BigDecimal getConversionRate() {
            Factor resultCollector = this.clone();

            resultCollector.substitute(new BigDecimal("0.3048"), this.CONSTANT_FT2M);
            resultCollector.substitute(new BigDecimal("411557987.0").divide(new BigDecimal("131002976.0"), DECIMAL128), this.CONSTANT_PI);
            resultCollector.substitute(new BigDecimal("9.80665"), this.CONSTANT_GRAVITY);
            resultCollector.substitute(new BigDecimal("6.67408E-11"), this.CONSTANT_G);
            resultCollector.substitute(new BigDecimal("0.00454609"), this.CONSTANT_GAL_IMP2M3);
            resultCollector.substitute(new BigDecimal("0.45359237"), this.CONSTANT_LB2KG);

            return resultCollector.factorNum.divide(resultCollector.factorDen, DECIMAL128);
        }

        private void substitute(BigDecimal value, int power) {
            if (power == 0) return;

            BigDecimal absPoweredValue = value.pow(Math.abs(power), DECIMAL128);
            if (power > 0) {
                this.factorNum = this.factorNum.multiply(absPoweredValue);
            } else {
                this.factorDen = this.factorDen.multiply(absPoweredValue);
            }
        }

        public Factor applySiPrefix(MeasureUnit.SIPrefix siPrefix) {
            Factor result = this.clone();
            if (siPrefix == MeasureUnit.SIPrefix.ONE) {
                return result;
            }

            BigDecimal siApplied = BigDecimal.valueOf(Math.pow(10.0, Math.abs(siPrefix.getSiPrefixPower())));

            if (siPrefix.getSiPrefixPower() < 0) {
                result.factorDen = this.factorDen.multiply(siApplied);
                return result;
            }

            result.factorNum = this.factorNum.multiply(siApplied);
            return result;
        }

        public Factor power(int power) {
            Factor result = new Factor();
            if (power == 0) return result;
            if (power > 0) {
                result.factorNum = this.factorNum.pow(power);
                result.factorDen = this.factorDen.pow(power);
            } else {
                result.factorNum = this.factorDen.pow(power * -1);
                result.factorDen = this.factorNum.pow(power * -1);
            }

            result.CONSTANT_FT2M = this.CONSTANT_FT2M * power;
            result.CONSTANT_PI = this.CONSTANT_PI * power;
            result.CONSTANT_GRAVITY = this.CONSTANT_GRAVITY * power;
            result.CONSTANT_G = this.CONSTANT_G * power;
            result.CONSTANT_GAL_IMP2M3 = this.CONSTANT_GAL_IMP2M3 * power;
            result.CONSTANT_LB2KG = this.CONSTANT_LB2KG * power;

            return result;
        }

        public Factor divide(Factor other) {
            Factor result = new Factor();
            result.factorNum = this.factorNum.multiply(other.factorDen);
            result.factorDen = this.factorDen.multiply(other.factorNum);

            result.CONSTANT_FT2M = this.CONSTANT_FT2M - other.CONSTANT_FT2M;
            result.CONSTANT_PI = this.CONSTANT_PI - other.CONSTANT_PI;
            result.CONSTANT_GRAVITY = this.CONSTANT_GRAVITY - other.CONSTANT_GRAVITY;
            result.CONSTANT_G = this.CONSTANT_G - other.CONSTANT_G;
            result.CONSTANT_GAL_IMP2M3 = this.CONSTANT_GAL_IMP2M3 - other.CONSTANT_GAL_IMP2M3;
            result.CONSTANT_LB2KG = this.CONSTANT_LB2KG - other.CONSTANT_LB2KG;

            return result;
        }

        public Factor multiply(Factor other) {
            Factor result = new Factor();
            result.factorNum = this.factorNum.multiply(other.factorNum);
            result.factorDen = this.factorDen.multiply(other.factorDen);

            result.CONSTANT_FT2M = this.CONSTANT_FT2M + other.CONSTANT_FT2M;
            result.CONSTANT_PI = this.CONSTANT_PI + other.CONSTANT_PI;
            result.CONSTANT_GRAVITY = this.CONSTANT_GRAVITY + other.CONSTANT_GRAVITY;
            result.CONSTANT_G = this.CONSTANT_G + other.CONSTANT_G;
            result.CONSTANT_GAL_IMP2M3 = this.CONSTANT_GAL_IMP2M3 + other.CONSTANT_GAL_IMP2M3;
            result.CONSTANT_LB2KG = this.CONSTANT_LB2KG + other.CONSTANT_LB2KG;

            return result;
        }

        /**
         * Adds Entity with power or not. For example, `12 ^ 3` or `12`.
         *
         * @param poweredEntity
         */
        private void addPoweredEntity(String poweredEntity) {
            String[] entities = poweredEntity.split(Pattern.quote("^"));
            assert (entities.length == 1 || entities.length == 2);

            int power = entities.length == 2 ? Integer.parseInt(entities[1]) : 1;
            this.addEntity(entities[0], power);
        }

        private void addEntity(String entity, int power) {
            if ("ft_to_m".equals(entity)) {
                this.CONSTANT_FT2M += power;
            } else if ("ft2_to_m2".equals(entity)) {
                this.CONSTANT_FT2M += 2 * power;
            } else if ("ft3_to_m3".equals(entity)) {
                this.CONSTANT_FT2M += 3 * power;
            } else if ("in3_to_m3".equals(entity)) {
                this.CONSTANT_FT2M += 3 * power;
                this.factorDen = this.factorDen.multiply(BigDecimal.valueOf(Math.pow(12, 3)));
            } else if ("gal_to_m3".equals(entity)) {
                this.factorNum = this.factorNum.multiply(BigDecimal.valueOf(231));
                this.CONSTANT_FT2M += 3 * power;
                this.factorDen = this.factorDen.multiply(BigDecimal.valueOf(12 * 12 * 12));
            } else if ("gal_imp_to_m3".equals(entity)) {
                this.CONSTANT_GAL_IMP2M3 += power;
            } else if ("G".equals(entity)) {
                this.CONSTANT_G += power;
            } else if ("gravity".equals(entity)) {
                this.CONSTANT_GRAVITY += power;
            } else if ("lb_to_kg".equals(entity)) {
                this.CONSTANT_LB2KG += power;
            } else if ("PI".equals(entity)) {
                this.CONSTANT_PI += power;
            } else {
                BigDecimal decimalEntity = new BigDecimal(entity).pow(power, DECIMAL128);
                this.factorNum = this.factorNum.multiply(decimalEntity);
            }
        }
    }
}
