/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.math;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.ranides.assira.collection.map.Pair;
import net.ranides.assira.collection.map.SwitchMap;
import net.ranides.assira.text.StringUtils;

/**
 *
 * @author ranides
 */
public final class Numeric {

    @java.lang.SuppressWarnings("unchecked")
    private static final Map<String, Long> PREFIX = new SwitchMap<>(new Pair[]{
        Pair.make("K", 1024L),
        Pair.make("M", 1024L * 1024L),
        Pair.make("G", 1024L * 1024L * 1024L),
        Pair.make("T", 1024L * 1024L * 1024L * 1024L),
        Pair.make("k", 1000L),
        Pair.make("m", 1000L * 1000L),
        Pair.make("g", 1000L * 1000L * 1000L),
        Pair.make("t", 1000L * 1000L * 1000L * 1000L)
    });

    private static final Pattern PATTERN_ENG = Pattern.compile("([0-9\\. ]+)([KMGTkmgt])?([Bb])?");

    private Numeric() { /* utility class */ }

    public static long asLong(String value, long ddefault) {
        try {
            return asLong(value);
        } catch(NumberFormatException _e) {
            return ddefault;
        }
    }

    public static int asInt(String value, int ddefault) {
        try {
            return asInt(value);
        } catch(NumberFormatException _e) {
            return ddefault;
        }
    }

    public static short asShort(String value, short ddefault) {
        try {
            return asShort(value);
        } catch(NumberFormatException _e) {
            return ddefault;
        }
    }

    public static float asFloat(String value, float ddefault) {
        try {
            return asFloat(value);
        } catch(NumberFormatException _e) {
            return ddefault;
        }
    }

    public static double asDouble(String value, double ddefault) {
        try {
            return asDouble(value);
        } catch(NumberFormatException _e) {
            return ddefault;
        }
    }

    public static long asLong(String value) {
        Matcher hit = PATTERN_ENG.matcher(value);
        if(hit.matches()) {
            return asLong(hit);
        } else {
            return Long.parseLong( value.trim() );
        }
    }

    public static int asInt(String value) {
        Matcher hit = PATTERN_ENG.matcher(value);
        if(hit.matches()) {
            return (int)asLong(hit);
        } else {
            return Integer.parseInt( value.trim() );
        }
    }

    public static short asShort(String value) {
        Matcher hit = PATTERN_ENG.matcher(value);
        if(hit.matches()) {
            return (short)asLong(hit);
        } else {
            return Short.parseShort( value.trim() );
        }
    }

    public static float asFloat(String value) {
        Matcher hit = PATTERN_ENG.matcher(value);
        if(hit.matches()) {
            return (float)asDouble(hit);
        } else {
            return Float.parseFloat( value.trim() );
        }
    }

    public static double asDouble(String value) {
        Matcher hit = PATTERN_ENG.matcher(value);
        if(hit.matches()) {
            return asDouble(hit);
        } else {
            return Double.parseDouble( value.trim() );
        }
    }

    private static double asDouble(Matcher hit) {
        double value = Double.parseDouble(StringUtils.remove(hit.group(1),' '));
        if(null !=hit.group(2)) {
            value *= PREFIX.get(hit.group(2));
        }
        if("b".equals(hit.group(3))) {
            value /= 8;
        }
        return value;
    }

    private static long asLong(Matcher hit) {
        long value = Long.parseLong(StringUtils.remove(hit.group(1),' '));
        if(null !=hit.group(2)) {
            value *= PREFIX.get(hit.group(2));
        }
        if("b".equals(hit.group(3))) {
            value /= 8;
        }
        return value;
    }

    public static String format(long value) {
        StringBuilder ret = new StringBuilder();
        String text = Long.toString(value, 10);
        for(int i=0, n=text.length()-1; i<=n; i++) {
            ret.append(text.charAt(i));
            if( n>i && ((n-i)%3 == 0) ) {
                ret.append('\'');
}
        }
        return ret.toString();
    }

}
