package test;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 *
 * @author MazenB
 */
public class ArabicLiteralNumberParser {

    private static final String ZERO = "صفر";
    private static final String ONE = "واحد";
    private static final String TWO = "إثنان";
    private static final String THREE = "ثلاثة";
    private static final String FOUR = "أربعة";
    private static final String FIVE = "خمسة";
    private static final String SIX = "ستة";
    private static final String SEVEN = "سبعة";
    private static final String EIGHT = "ثمانية";
    private static final String NINE = "تسعة";
    private static final String TEN = "عشرة";
    private static final String TWENTY = "عشرون";
    private static final String THIRTY = "ثلاثون";
    private static final String FOURTY = "أربعون";
    private static final String FIFTY = "خمسون";
    private static final String SIXTY = "ستون";
    private static final String SEVENTY = "سبعون";
    private static final String EIGHTY = "ثمانون";
    private static final String NINETY = "تسعون";
    private static final String HUNDRED = "مائة";
    private static final String THOUSAND = "الف";
    private static final String MILLION = "مليون";
    private static final String MILLIARD = "مليار";
    private static final String BILLION = "بليون";
    private static final String BILLIARD = "بليار";
    private static final String TRILLION = "تريليون";
    private static final Map<Long, String> namesMap;


    static {

        namesMap = new HashMap<Long, String>();
        namesMap.put(0l, ZERO);
        namesMap.put(1l, ONE);
        namesMap.put(2l, TWO);
        namesMap.put(3l, THREE);
        namesMap.put(4l, FOUR);
        namesMap.put(5l, FIVE);
        namesMap.put(6l, SIX);
        namesMap.put(7l, SEVEN);
        namesMap.put(8l, EIGHT);
        namesMap.put(9l, NINE);
        namesMap.put(10l, TEN);
        namesMap.put(20l, TWENTY);
        namesMap.put(30l, THIRTY);
        namesMap.put(40l, FOURTY);
        namesMap.put(50l, FIFTY);
        namesMap.put(60l, SIXTY);
        namesMap.put(70l, SEVENTY);
        namesMap.put(80l, EIGHTY);
        namesMap.put(90l, NINETY);
        namesMap.put(100l, HUNDRED);
        namesMap.put(1000l, THOUSAND);
        namesMap.put(1000000l, MILLION);
        namesMap.put(1000000000l, MILLIARD);//billion in short scale (US)
        namesMap.put(1000000000000l, BILLION);//trillion //
        namesMap.put(1000000000000000l, BILLIARD);//quadrllion //
        namesMap.put(1000000000000000000l, TRILLION);//quintillion //
    }

    private static String parse(long a, boolean fe) {
        StringBuffer buf = new StringBuffer(Long.valueOf(a).toString());
        buf.reverse();
        int index = 0;
        boolean negative;
        int len = (negative = buf.charAt(buf.length() - 1) == '-') ? buf.length() - 1 : buf.length();

        String[] name = new String[len];
        long unitValue = 0;
        while (index < len) {
            Long n = Long.valueOf(String.valueOf(buf.charAt(index)));
            int decimalPos = index % 3;
            if (decimalPos == 0) {
                unitValue = Double.valueOf(Math.pow(10, index)).longValue();
            }
            int decimalPlace = (Double.valueOf(Math.pow(10, decimalPos)).intValue());
            switch (decimalPlace) {
                case 1:
                    if (unitValue > 1l && index + 1 == len) {
                        switch (n.intValue()) {
                            case 1:
                                name[index] = namesMap.get(unitValue);
                                break;
                            case 2:
                                name[index] = namesMap.get(unitValue) + "ان";
                                break;
                            default:
                                String val = namesMap.get(n);
                                val = val.substring(0, val.length() - (n == 8 ? 2 : 1));
                                if (unitValue == 1000l) {
                                    name[index] = val + " " + "الاف";
                                } else if (unitValue == 1000000l) {
                                    name[index] = val + " " + "ملايين";
                                } else {
                                    name[index] = val + " " + namesMap.get(unitValue) + "ات";
                                }
                        }
                    } else {
                        String val = namesMap.get(n);
                        if (index + 1 == len) {
                            if (fe && n > 2) {
                                val = val.substring(0, val.length() - (n == 8 ? 2 : 1));
                            } else if (fe && n != 0) {
                                val = n == 1 ? "واحدة" : "إثنتان";
                            }
                        }
                        name[index] = val;
                    }
                    break;
                case 10:
                    String tmp = name[index - 1];

                    if (n != 0 && !tmp.equals(ZERO)) {
                        Iterator i = namesMap.keySet().iterator();
                        while (i.hasNext()) {
                            Long val = (Long) i.next();
                            if (namesMap.get(val).equals(tmp)) {
                                switch (val.intValue()) {
                                    case 1:
                                        if (fe) {
                                            tmp = n == 1 ? "إحدى" : "واحدة";
                                        } else {
                                            tmp = n == 1 ? "احد" : "واحد";
                                        }
                                        break;
                                    case 2:
                                        if (fe) {
                                            tmp = n == 1 ? "إثنتا" : "إثنتان";
                                        } else {
                                            tmp = n == 1 ? "إثنا" : "إثنان";
                                        }
                                        break;
                                    default:
                                        tmp = fe ? tmp.substring(0, tmp.length() - (val == 8 ? 2 : 1)) : tmp;
                                }
                                break;
                            }
                        }
                    }
                    name[index] = namesMap.get(n * 10l);

                    if (index + 1 == len) {
                        switch (n.intValue()) {
                            case 1:
                                if (tmp.equals(ZERO)) {
                                    String val = fe ? "عشر" : "عشرة";
                                    if (unitValue == 1000l) {
                                        name[index] = val + " " + "الاف";
                                    } else if (unitValue == 1000000l) {
                                        name[index] = val + " " + "ملايين";
                                    } else {
                                        name[index] = val + (unitValue > 1 ? " " + namesMap.get(unitValue) + "ات" : "");
                                    }
                                    break;
                                }
                                name[index] = fe ? "عشرة" : "عشر";
                            default:
                                if (unitValue > 1) {
                                    name[index] = name[index] + " " + namesMap.get(unitValue) + "ا";
                                }
                        }

                    }
                    if (n != 0l) {
                        name[index - 1] = name[index];
                        name[index] = tmp;
                    }

                    break;
                case 100:

                    String s;
                    if (n > 2) {
                        s = namesMap.get(n);
                        s = s.substring(0, s.length() - (n == 8 ? 2 : 1)) + HUNDRED;
                    } else {
                        s = n == 2 ? "مائتان" : namesMap.get(n * 100);
                    }
                    if (!name[index - 2].equals(ZERO)) {
                        Iterator i = namesMap.keySet().iterator();
                        while (i.hasNext()) {
                            Long val = (Long) i.next();
                            if (namesMap.get(val).equals(name[index - 2])) {
                                if (fe && val < 10) {

                                    name[index - 2] = val == 1 ? "واحدة" : val == 2 ? "إثنتان" : name[index - 2].substring(0, name[index - 2].length() - (val == 8 ? 2 : 1));

                                } else if (val == 10 && fe == name[index - 1].equals(ZERO)) {
                                    name[index - 2] = "عشر";
                                }
                                if (unitValue > 1) {
                                    switch (val.intValue()) {
                                        case 1:
                                        case 2:
                                            name[index - 2] = name[index - 2] + " " + namesMap.get(unitValue);
                                            break;
                                        case 10:
                                            if (!name[index - 1].equals(ZERO)) {
                                                name[index - 2] = name[index - 2] + " " + namesMap.get(unitValue) + "ا";
                                                break;
                                            }

                                        default:
                                            if (val > 10l) {
                                                name[index - 2] = name[index - 2] + " " + namesMap.get(unitValue) + "ا";

                                            } else {
                                                if (unitValue == 1000l) {
                                                    name[index - 2] = name[index - 2] + " " + "الاف";
                                                } else if (unitValue == 1000000l) {
                                                    name[index - 2] = name[index - 2] + " " + "ملايين";
                                                } else {
                                                    name[index - 2] = name[index - 2] + " " + namesMap.get(unitValue) + "ات";
                                                }
                                            }

                                    }
                                }
                                break;
                            }
                        }

                    } else if (unitValue > 1l && n != 0) {
                        s = (n == 2 ? "مائتا" : s) + " " + namesMap.get(unitValue);////6
                    }

                    name[index] = s;

            }
            index++;
        }


        String s = "";
        for (int i = 0; i < len; i++) {

            if (name[i].equals(ZERO)) {
                continue;
            }
            name[i] = name[i].trim();
            s = name[i] + (!s.isEmpty() && !((s.startsWith("عشر") && !s.startsWith(TWENTY)) && !name[i - 1].equals(ZERO)) ? " و" : " ") + s;///7

        }
        return s.isEmpty() ? ZERO : (negative ? "سالب " + s : s).trim();
    }

    public static String literalValueOf(Number a, boolean fe) {

        if (a.doubleValue() > Long.MAX_VALUE) {
            return " اكبر من " + parse(Long.MAX_VALUE, fe);
        }
        a = String.valueOf(a).toLowerCase().contains("e") ? a.longValue() : a;

        String[] array = String.valueOf(a).split("\\.");

        long i = Long.valueOf(array[0]);
        long f = array.length == 2 ? Long.valueOf(array[1]) : 0;

        int fractSize = f > 0 ? array[1].length() : 0;

        String integralPart = (i != 0 || f == 0) ? parse(i, fe) : "";

        String fractionalPart = f > 0 ? parse(f, fe) + " من " + parse(Double.valueOf(Math.pow(10, fractSize)).longValue(), fe) : "";

        return integralPart + (f * i != 0 ? " و " : "") + fractionalPart;
    }

    public static String literalValueOf(Number a) {
        return literalValueOf(a, false);
    }

    ///For testing, please remove!
    public static void main(String[] args) {
        System.out.println(literalValueOf(7912687.3, true));

    }
}

