package com.brilliance.mda.runtime.mda.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

import static com.brilliance.mda.runtime.mda.Constants.NULLSTR;

public class Formats {

    private static final Logger log = LoggerFactory.getLogger(Formats.class);

    private static final String EMPTY_STRING = "";

    public static String format(Date dattim, String dateFormat, String lang, String timezone) {
        return format(dattim,dateFormat);
    }
    public static String format(Date dattim, String dateFormat, String lang) {
        return format(dattim,dateFormat);
    }

    /**
     * language语言详情请参考 SimpleDateFormat(language)构造函数<br>
     * 建议直接使用 formatDate(Date dattim, String dateFormat, Locale locale),<br>
     * 底层用的是 SimpleDateFormat（locale)构造函数
     *
     * @param dattim
     * @param dateFormat
     * @param language
     * @return
     */
    public static String formatDate(Date dattim, String dateFormat, String language) {
        return formatDate(dattim,dateFormat,new Locale(language));
    }


    /**
     *  language以及country详情请参考 SimpleDateFormat(language,country)构造函数<br>
     *  建议直接使用 formatDate(Date dattim, String dateFormat, Locale locale)<br>
     *  底层用的是 SimpleDateFormat（locale)构造函数
     * @param dattim
     * @param dateFormat
     * @param language
     * @param country
     * @return
     */
    public static String formatDate(Date dattim, String dateFormat, String language,String country) {
        return formatDate(dattim,dateFormat,new Locale(language,country));
    }

    /**
     * 添加一个带locale的选项，格式化日期
     *
     *
     * @param dattim
     * @param dateFormat
     * @param locale
     * @return
     */
    public static String formatDate(Date dattim, String dateFormat, Locale locale) {
        // 如果dattim为null，则返回空字符串
        if(null == dattim){
            return EMPTY_STRING;
        }
        // dateFormat中的'D'代表的是一年中的天数，通常情况下我们需要的是一个月中的天数‘d'
        dateFormat = dateFormat.replaceAll("D", "d");
        return new SimpleDateFormat(dateFormat,locale).format(dattim);
    }

    /**
     * 默认使用当前环境所在的地区格式化日期
     *
     * @param dattim
     * @param dateFormat
     * @return
     */
    public static String formatDate(Date dattim, String dateFormat) {
        // 如果dattim为null，则返回空字符串
        if(null == dattim){
            return EMPTY_STRING;
        }
        // dateFormat中的'D'代表的是一年中的天数，通常情况下我们需要的是一个月中的天数‘d'
        dateFormat = dateFormat.replaceAll("D", "d");
        return new SimpleDateFormat(dateFormat).format(dattim);
    }


    public static String format(Object object, String pattern) {
        if (object == null)
            return "";
        if ((object instanceof Number))
            return new DecimalFormat(pattern).format(object);
        if ((object instanceof Date)) {
            pattern = pattern.replaceAll("D", "d");
            return new SimpleDateFormat(pattern).format(object);
        }
        if (pattern.startsWith("%"))
            return String.format(pattern, new Object[]{object});
        return new MessageFormat(pattern).format(object);
    }

    static String covEnAmt(BigDecimal amt) {
        if (amt == null)
            return "";
        String strAmt = amt.setScale(2, 4).toString();
        String[] words1 = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
        String[] words4 = { "hundred", "thousand", "million", "billion", "trillion" };
        int idx = strAmt.indexOf(".");
        String sInt = strAmt.substring(0, idx);
        String sFlt = strAmt.substring(idx + 1);
        int lenZ = sInt.length();
        if (lenZ > 15)
            return "";
        String en = "";
        if (lenZ > 12) {
            String str = sInt.substring(0, lenZ - 9);
            if (!"000".equals(str))
                en = String.valueOf(en) + convertdhundred(str) + " " + words4[4] + " ";
            sInt = sInt.substring(lenZ - 9);
            lenZ = sInt.length();
        }
        if (lenZ > 9) {
            String str = sInt.substring(0, lenZ - 9);
            if (!"000".equals(str))
                en = String.valueOf(en) + convertdhundred(str) + " " + words4[3] + " ";
            sInt = sInt.substring(lenZ - 9);
            lenZ = sInt.length();
        }
        if (lenZ > 6) {
            String str = sInt.substring(0, lenZ - 6);
            if (!"000".equals(str))
                en = String.valueOf(en) + convertdhundred(str) + " " + words4[2] + " ";
            sInt = sInt.substring(lenZ - 6);
            lenZ = sInt.length();
        }
        if (lenZ > 3) {
            String str = sInt.substring(0, lenZ - 3);
            if (!"000".equals(str))
                en = String.valueOf(en) + convertdhundred(str) + " " + words4[1] + " ";
            sInt = sInt.substring(lenZ - 3);
            lenZ = sInt.length();
        }
        String s = sInt;
        if (!"000".equals(s))
            en = String.valueOf(en) + convertdhundred(s);
        int lenF = sFlt.length();
        if (lenF > 0) {
            String w2 = " ";
            boolean allZero = true;
            for (int i = 0; i < lenF; i++) {
                int n = sFlt.charAt(i) - 48;
                w2 = String.valueOf(w2) + words1[n] + " ";
                if (n > 0)
                    allZero = false;
            }
            if (!"0".equals(s)) {
                w2 = " and cents " + convertdhundred(sFlt);
            } else {
                w2 = " cents " + convertdhundred(sFlt);
            }
            if (!allZero) {
                en = String.valueOf(en) + w2;
            } else {
                en = String.valueOf(en) + " only ";
            }
        } else {
            en = String.valueOf(en) + " only ";
        }
        return en;
    }

    static String convertdhundred(String s) {
        String[] words1 = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
        String[] words2 = { "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen",
                "eighteen", "nineteen" };
        String[] words3 = { "", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };
        String[] words4 = { "hundred", "thousand", "million", "billion" };
        char c1 = '0';
        char c2 = '0';
        char c3 = '0';
        if (s.length() > 2) {
            c1 = s.charAt(0);
            c2 = s.charAt(1);
            c3 = s.charAt(2);
        } else if (s.length() > 1) {
            c1 = '0';
            c2 = s.charAt(0);
            c3 = s.charAt(1);
        } else if (s.length() > 0) {
            c1 = '0';
            c2 = '0';
            c3 = s.charAt(0);
        }
        int n1 = c1 - 48;
        int n2 = c2 - 48;
        int n3 = c3 - 48;
        String word = "";
        if (n1 > 0)
            word = String.valueOf(word) + words1[n1] + " " + words4[0] + " ";
        if (n1 != 0 && n2 == 0 && n3 != 0)
            word = String.valueOf(word) + " and ";
        if (n2 == 1) {
            word = String.valueOf(word) + words2[n3] + " ";
        } else if (n2 > 1) {
            word = String.valueOf(word) + words3[n2] + " ";
            if (n3 > 0)
                word = String.valueOf(word) + words1[n3];
        } else if (n3 > 0) {
            word = String.valueOf(word) + words1[n3];
        }
        return word.trim();
    }

    public static String covCnAmt(BigDecimal amt) {
        try {
            if (amt == null)
                return "";
            String strAmt = amt.setScale(2, 4).toString();
            String[] number = { "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
            String[] radices = { "仟", "", "拾", "佰" };
            String[] bigRadices = { "", "万", "亿", "万亿", "亿亿" };
            int idx = strAmt.indexOf(".");
            String sInt = strAmt.substring(0, idx);
            String sFlt = strAmt.substring(idx + 1);
            String cn = "";
            int zeroC = 0;
            int len = sInt.length();
            for (int i = 0; i < len; i++) {
                if (sInt.charAt(i) == '0') {
                    zeroC++;
                } else {
                    if (zeroC > 0) {
                        cn = String.valueOf(cn) + "零";
                        zeroC = 0;
                    }
                    cn = String.valueOf(cn) + number[sInt.charAt(i) - 49];
                    cn = String.valueOf(cn) + radices[(len - i) % 4];
                }
                if ((len - i) % 4 == 1 && zeroC < 4)
                    cn = String.valueOf(cn) + bigRadices[(len - i) / 4];
            }
            cn = String.valueOf(cn) + "元";
            if (sFlt.equals("00")) {
                cn = String.valueOf(cn) + "整";
            } else {
                if (!sFlt.substring(0, 1).equals("0")) {
                    cn = String.valueOf(cn) + number[sFlt.charAt(0) - 49] + "角";
                } else {
                    cn = String.valueOf(cn) + "零";
                }
                if (!sFlt.substring(1, 2).equals("0"))
                    cn = String.valueOf(cn) + number[sFlt.charAt(1) - 49] + "分";
            }
            log.debug("cn===" + cn);
            return cn;
        } catch (Exception e) {
            log.error("covCnAmt error", e);
            return "";
        }
    }

    public static String fmtDateLong(Date date) {
        return Dates.toLocalDate(date).format(DateTimeFormatter.BASIC_ISO_DATE);
    }

    public static String fmtDateLong(Date today, String language) {
        if (today == null) return NULLSTR;
        Calendar c = Calendar.getInstance();
        c.setTime(today);
        if(language == null)
            c.setTimeZone(TimeZone.getDefault());
        else
            c.setTimeZone(TimeZone.getTimeZone(language));
        return fmtDateLong(c.getTime());
    }

    public static String fmtDateShort(Date date) {
        if (date == null) return NULLSTR;
        return fmtDateLong(date, null);
    }

    public static String fmtDateShort(Date date, String fmt) {
        if (date == null) return NULLSTR;
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        return format.format(date);
    }

    public static String fmtAmount(Integer fmtamt, String cur, String LANG) {
        return fmtAmount(new BigDecimal(fmtamt), cur, LANG);
    }

    public static String fmtAmount(Double fmtamt, String cur, String LANG) {
        return fmtAmount(new BigDecimal(Double.toString(fmtamt)), cur, LANG);
    }

    public static String fmtAmount(BigDecimal fmtamt, String cur, String LANG) {
        if (fmtamt == null){
            fmtamt = BigDecimal.ZERO;
        }
        String amt = fmtamt.toString();
        String intVal;
        String fractionVal;
        if (amt.contains(".")) {
            String[] split = amt.split("\\.");
            intVal = split[0];
            fractionVal = split[1];
        } else {
            intVal = amt;
            fractionVal = "00";
        }
        int length = intVal.length();
        int num = length / 3;
        int md = length % 3;
        StringBuilder sb = new StringBuilder();
        sb.append(intVal, 0, md);
        for (int i = 0; i < num; i++) {
            if (md != 0 || i != 0) {
                sb.append(",");
            }
            sb.append(intVal, 3 * i + md, 3 * (i + 1) + md);
        }
        if (!"JPY".equals(cur)) {
            sb.append(".").append(fractionVal);
        }
        return sb.toString();
    }

    public static String fmtAmount(BigDecimal fmtamt, String cur) {
        return fmtAmount(fmtamt, cur, Systems.getLang());
    }

    public static String fmtAmount(double fmtamt, String cur) {
        return fmtAmount(BigDecimal.valueOf(fmtamt), cur, Systems.getLang());
    }
}
