/* UtilLib - Copyright (c) 2012-2018 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package net.mapeadores.util.money;

import net.mapeadores.util.exceptions.ShouldNotOccurException;
import net.mapeadores.util.primitives.Decimal;


/**
 *
 * @author Vincent Calame
 */
public class MoneyLong {

    private MoneyLong() {
    }

    public static long toMoneyLong(Decimal decimal, int fractionDigits) {
        int multiplicator = MoneyUtils.toMultiplicator(fractionDigits);
        long lg = decimal.getPartieEntiere() * multiplicator;
        int partieDecimale = decimal.getPartieDecimale();
        if (partieDecimale == 0) {
            return lg;
        }
        byte zeroLength = decimal.getZeroLength();
        if (zeroLength > fractionDigits) {
            return lg;
        }
        boolean neg = false;
        if (lg < 0) {
            lg = -lg;
            neg = true;
        }
        if (partieDecimale < 0) {
            partieDecimale = -partieDecimale;
            neg = true;
        }
        lg = lg + getDecimalPart(zeroLength, partieDecimale, fractionDigits);
        if (neg) {
            lg = -lg;
        }
        return lg;
    }

    public static Decimal toDecimal(long l, int fractionDigits, boolean avoidDecimal) {
        int multiplicator = MoneyUtils.toMultiplicator(fractionDigits);
        long partieEntiere = l / multiplicator;
        int partieDecimale = (int) (l % multiplicator);
        byte zeroLength = 0;
        if (partieDecimale == 0) {
            if (!avoidDecimal) {
                zeroLength = (byte) fractionDigits;
            }
        } else if (Math.abs(partieDecimale) < multiplicator) {
            String s = String.valueOf(Math.abs(partieDecimale));
            zeroLength = (byte) (fractionDigits - s.length());
        }
        return new Decimal(partieEntiere, zeroLength, partieDecimale);
    }

    public static String toString(long moneyLong, int fractionDigits) {
        StringBuilder buf = new StringBuilder();
        if (moneyLong == 0) {
            buf.append('0');
            if (fractionDigits > 0) {
                buf.append('.');
                for (int i = 0; i < fractionDigits; i++) {
                    buf.append('0');
                }
            }
            return buf.toString();
        }
        if (moneyLong < 0) {
            moneyLong = -moneyLong;
            buf.append('-');
        }
        String s = Long.toString(moneyLong);
        int longLength = s.length();
        if (longLength <= fractionDigits) {
            buf.append('0');
        } else {
            int entierLength = longLength - fractionDigits;
            for (int i = 0; i < entierLength; i++) {
                buf.append(s.charAt(i));
            }
        }
        if (fractionDigits > 0) {
            buf.append('.');
            int depart = (longLength - fractionDigits);
            if (depart < 0) {
                depart = -depart;
                for (int i = 0; i < depart; i++) {
                    buf.append('0');
                }
                depart = 0;
            }
            for (int i = depart; i < longLength; i++) {
                buf.append(s.charAt(i));
            }
        }
        return buf.toString();
    }

    public static String toString(long moneyLong, int fractionDigits, char decimalSeparator, char groupingSeparator, boolean avoidDecimal) {
        StringBuilder buf = new StringBuilder();
        if (moneyLong == 0) {
            buf.append('0');
            if (!avoidDecimal) {
                if (fractionDigits > 0) {
                    buf.append(decimalSeparator);
                    for (int i = 0; i < fractionDigits; i++) {
                        buf.append('0');
                    }
                }
            }
            return buf.toString();
        }
        if (moneyLong < 0) {
            moneyLong = -moneyLong;
            buf.append("- ");
        }
        String s = Long.toString(moneyLong);
        int longLength = s.length();
        if (longLength <= fractionDigits) {
            buf.append('0');
        } else {
            int entierLength = longLength - fractionDigits;
            if (entierLength <= 3) {
                for (int i = 0; i < entierLength; i++) {
                    buf.append(s.charAt(i));
                }
            } else {
                int reste = entierLength % 3;
                if (reste > 0) {
                    buf.append(s.charAt(0));
                    if (reste > 1) {
                        buf.append(s.charAt(1));
                    }
                    buf.append(groupingSeparator);
                }
                int p = 0;
                for (int i = reste; i < entierLength; i++) {
                    buf.append(s.charAt(i));
                    p++;
                    if (p == 3) {
                        if (i < (entierLength - 1)) {
                            buf.append(groupingSeparator);
                        }
                        p = 0;
                    }
                }
            }
        }
        if (fractionDigits > 0) {
            boolean append = true;
            int depart = (longLength - fractionDigits);
            if (depart < 0) {
                depart = -depart;
                buf.append(decimalSeparator);
                for (int i = 0; i < depart; i++) {
                    buf.append('0');
                }
                depart = 0;
            } else {
                if (avoidDecimal) {
                    boolean withDecimal = false;
                    for (int i = depart; i < longLength; i++) {
                        if (s.charAt(i) != '0') {
                            withDecimal = true;
                            break;
                        }
                    }
                    if (!withDecimal) {
                        append = false;
                    }
                }
                if (append) {
                    buf.append(decimalSeparator);
                }
            }
            if (append) {
                for (int i = depart; i < longLength; i++) {
                    buf.append(s.charAt(i));
                }
            }
        }
        return buf.toString();
    }

    private static int getDecimalPart(byte zeroLength, int partieDecimale, int totalLength) {
        StringBuilder buf = new StringBuilder();
        for (int i = 0; i < zeroLength; i++) {
            buf.append('0');
            totalLength = totalLength - 1;
        }
        String s = String.valueOf(partieDecimale);
        int decimalLength = s.length();
        int min = Math.min(decimalLength, totalLength);
        for (int i = 0; i < min; i++) {
            buf.append(s.charAt(i));
        }
        int chiffrearrondi = 0;
        if (min < totalLength) {
            for (int i = min; i < totalLength; i++) {
                buf.append('0');
            }
        } else if (min < decimalLength) {
            chiffrearrondi = ((int) s.charAt(min)) - 48;
        }
        try {
            int result = 0;
            if (buf.length() > 0) {
                result = Integer.parseInt(buf.toString());
            }
            if (chiffrearrondi >= 5) {
                result = result + 1;
            }
            return result;
        } catch (NumberFormatException nfe) {
            throw new ShouldNotOccurException();
        }

    }

}
