package com.artfess.base.util;

import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class CommonUtil {
    //本地异常日志记录对象

    public static final long HOURS_PER_DAY = 24L;
    public static final long SECS_PER_MIN = 60L;
    public static final long MINS_PER_HOUR = 60L;
    public static final long MILLIS_PER_SECOND = 1000L;
    public static final long MILLIS_PER_MINUTE = 60000L;
    public static final long MILLIS_PER_HOUR = 3600000L;
    public static final long MILLIS_PER_DAY = 86400000L;
    public static final int DEFAULT_SCALE = 20;
//	static SimpleDateFormat sdf = null;

    public static Map<String, Object> decodeMap(String value) {
        HashMap<String, Object> result = new HashMap<String, Object>();
        if (StringUtil.isNotEmpty(value)) {
            String[] valueArray = value.trim().split(";");
            for (String str : valueArray) {
                if (str.contains("=")) {
                    String[] subValueArray = str.trim().split("=");
                    if (subValueArray.length == 1)
                        result.put(subValueArray[0].trim(), "");
                    else {
                        result.put(subValueArray[0].trim(),subValueArray[1].trim());
                    }
                }
            }
        }
        return result;
    }

    public static String encodeMap(Map<String, Object> map) {
        String result = "";
        for (String key : map.keySet()) {
            Object obj = map.get(key);
            String value = "";
            if (obj != null) {
                value = obj + "";
            }
            result = result + key + "=" + value + ";";
        }
        return result;
    }

    public static String createGUID() {
        return UUID.randomUUID().toString().toUpperCase().replaceAll("-", "");
    }

    public static String createFileFullName(String path, String fileName, String fileKind) {
        StringBuffer sb = new StringBuffer();
        sb.append(StringUtil.isEmpty(path) ? "" : path);
        sb.append("/");
        sb.append(StringUtil.isEmpty(fileName) ? "" : fileName);
        if (StringUtil.isNotEmpty(fileKind))
            sb.append(".").append(fileKind);
        return sb.toString();
    }

    public static Timestamp getCurrentDateTime() {
        return new Timestamp(new Date().getTime());
    }

    public static java.sql.Date getCurrentDate() {
        return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd")
                .format(new Date()));
    }

    public static Date trunc(Date value) throws ParseException {
        String dateStr = new SimpleDateFormat("yyyy-MM-dd").format(value);
        return new SimpleDateFormat("yyyy-MM-dd").parse(dateStr);
    }

    public static Date parseDateTime(String value) throws ParseException{
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value);
    }

    public static java.sql.Date getYesterday() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(getCurrentDate());
        calendar.add(5, -1);

        return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
    }

    public static java.sql.Date getTomorrow() {
        Calendar calendar = Calendar.getInstance();

        calendar.setTime(getCurrentDate());
        calendar.add(5, 1);

        return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
    }

    public static Time getCurrentTime() {
        return Time.valueOf(new SimpleDateFormat("HH:mm:ss").format(new Date()));
    }

    public static int getYear(Date date) {
        verification(date != null, "getYear的参数不能为空。");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(1);
    }

    public static int getMonth(Date date) {
        verification(date != null, "getMonth的参数不能为空。");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(2) + 1;
    }

    public static int getDay(Date date) {
        verification(date != null, "getDay的参数不能为空。");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(5);
    }

    public static int getHour(Date date) {
        verification(date != null, "getHour的参数不能为空。");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(10);
    }

    public static int getMinute(Date date) {
        verification(date != null, "getMinute的参数不能为空。");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(12);
    }

    public static java.sql.Date getFirstDateOfYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(2, 0);
        calendar.set(5, 1);
        return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
    }

    public static java.sql.Date getFirstDateOfYear(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(1, year);
        calendar.set(2, 0);
        calendar.set(5, 1);
        return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
    }

    public static java.sql.Date getLastDateOfYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(1, 1);
        calendar.set(2, 0);
        calendar.set(5, 0);
        return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
    }

    /**
     * 获得指定日期的前一天
     *
     * @param specifiedDay 指定日期
     * @param pattern      需要返回的日期格式，例如：yyyy-MM-dd HH:mm:ss
     * @return 前一天日期
     */
    public static String getSpecifiedDayBefore(String pattern, String specifiedDay) throws ParseException {
        Calendar c = Calendar.getInstance();
        Date date = new SimpleDateFormat(pattern).parse(specifiedDay);
        c.setTime(date);
        int day = c.get(Calendar.DATE);
        c.set(Calendar.DATE, day - 1);
        String dayBefore = new SimpleDateFormat(pattern).format(c.getTime());
        return dayBefore;
    }

    public static java.sql.Date getLastDateOfYear(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(1, year + 1);
        calendar.set(2, 0);
        calendar.set(5, 0);
        return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
    }

    public static java.sql.Date getFirstDateOfLastYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(1, -1);
        calendar.set(2, 0);
        calendar.set(5, 1);
        return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
    }

    public static java.sql.Date getLastDateOfLastYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(2, 0);
        calendar.set(5, 0);
        return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
    }

    public static Date addDays(Date date, int days) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(5, days);
        return calendar.getTime();
    }

    public static int getSecond(Date date) {
        verification(date != null, "getYear的参数不能为空！");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(13);
    }

    public static java.sql.Date getFirstDateOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(5, 1);
        return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
    }

    public static java.sql.Date getLastDateOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(2, 1);
        calendar.set(5, 0);
        return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
    }

    public static java.sql.Date getFirstDateOfLastMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(2, -1);
        calendar.set(5, 1);
        return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
    }

    public static java.sql.Date getLastDateOfLastMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        calendar.add(2, -1);

        int lastDay = calendar.getActualMaximum(5);
        calendar.set(5, lastDay);

        return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
    }

    public static java.sql.Date getFirstDateOfWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(7, 2);
        return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
    }

    public static java.sql.Date getLastDateOfWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(7, 7);
        calendar.add(5, 1);
        return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
    }

    public static java.sql.Date getFirstDateOfLastWeek(Date date) {
        Calendar calendar = Calendar.getInstance();

        java.sql.Date firstDayOfWeek = getFirstDateOfWeek(date);
        calendar.setTime(firstDayOfWeek);
        calendar.add(5, -7);

        return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
    }

    public static java.sql.Date getLastDateOfLastWeek(Date date) {
        Calendar calendar = Calendar.getInstance();

        java.sql.Date lastDayOfWeek = getFirstDateOfWeek(date);
        calendar.setTime(lastDayOfWeek);
        calendar.add(5, -1);

        return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
    }

    public static int getDayOfWeek(Date date) {
        Calendar localCalendar = Calendar.getInstance();
        localCalendar.setTime(date);
        return localCalendar.get(7);
    }

    public static java.sql.Date getStepDay(Date date, int step) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(6, step);
        return new java.sql.Date(calendar.getTime().getTime());
    }

    public static Integer getDaysBetween(Date start, Date end) {
        Assert.notNull(start, "参数start不能为空。");
        Assert.notNull(end, "参数end不能为空。");

        Long result = Long.valueOf((end.getTime() - start.getTime()) / 86400000L);
        return Integer.valueOf(result.intValue());
    }

    public static String toString(Object obj) {
        if (obj == null)
            return null;
        if ((obj instanceof Timestamp))
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) obj);
        if ((obj instanceof Time))
            return new SimpleDateFormat("HH:mm:ss").format((Date) obj);
        if ((obj instanceof java.sql.Date))
            return new SimpleDateFormat("yyyy-MM-dd").format((Date) obj);
        if ((obj instanceof BigDecimal))
            return new DecimalFormat("#.##################################").format(obj);
        return obj.toString();
    }

    public static int toInteger(Object obj) {
        verification(obj != null, "toInteger的参数不能为空。");
        if ((obj instanceof String))
            return Integer.valueOf((String) obj).intValue();
        if ((obj instanceof Number)) {
            return ((Number) obj).intValue();
        }
        throw new RuntimeException("错误的toInteger参数类型：" + obj.getClass());
    }

    public static BigDecimal toDecimal(Object obj) {
        verification(obj != null, "toDecimal的参数不能为空。");
        if ((obj instanceof BigDecimal)) {
            return (BigDecimal) obj;
        }
        BigDecimal result = null;
        if ((obj instanceof String))
            result = BigDecimal.valueOf(Double.valueOf((String) obj).doubleValue());
        else if ((obj instanceof Number))
            result = BigDecimal.valueOf(((Number) obj).doubleValue());
        else
            throw new RuntimeException("错误的toDecimal参数类型：" + obj.getClass());
        result.setScale(20, RoundingMode.HALF_UP);
        return result;
    }

    public static long toLong(Object obj) {
        verification(obj != null, "toLong的参数不能为空。");
        if ((obj instanceof String))
            return Long.valueOf((String) obj).longValue();
        if ((obj instanceof Number)) {
            return ((Number) obj).longValue();
        }
        throw new RuntimeException("错误的toLong参数类型：" + obj.getClass());
    }

    public static double toDouble(Object obj) {
        verification(obj != null, "toDouble的参数不能为空。");
        if ((obj instanceof String))
            return Double.valueOf((String) obj).doubleValue();
        if ((obj instanceof Number)) {
            return ((Number) obj).doubleValue();
        }
        throw new RuntimeException("错误的toDouble参数类型：" + obj.getClass());
    }

    public static float toFloat(Object obj) {
        verification(obj != null, "toFloat的参数不能为空。");
        if ((obj instanceof String))
            return Float.valueOf((String) obj).floatValue();
        if ((obj instanceof Number)) {
            return ((Number) obj).floatValue();
        }
        throw new RuntimeException("错误的toFloat参数类型：" + obj.getClass());
    }

    public static Float roundTo(Float value, int digit) {
        BigDecimal b = new BigDecimal(value.floatValue());
        return Float.valueOf(b.setScale(digit, 4).floatValue());
    }

    public static java.sql.Date toDate(Object obj) {
        verification(obj != null, "toDate的参数不能为空。");
        if ((obj instanceof java.sql.Date))
            return (java.sql.Date) obj;
        if ((obj instanceof String))
            return java.sql.Date.valueOf((String) obj);
        if ((obj instanceof Date))
            return java.sql.Date.valueOf(new SimpleDateFormat("yyyy-MM-dd").format((Date) obj));
        throw new RuntimeException("错误的toDate参数类型：" + obj.getClass());
    }

    public static Timestamp toDateTime(Object obj) {
        verification(obj != null, "toDateTime的参数不能为空。");
        if ((obj instanceof Timestamp))
            return (Timestamp) obj;
        if ((obj instanceof String))
            try {
                return new Timestamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse((String) obj).getTime());
            } catch (Exception localException) {
                throw new RuntimeException("将字符串：" + obj + "转换为DATETIME时出错！");
            }
        if ((obj instanceof Date))
            return new Timestamp(((Date) obj).getTime());
        throw new RuntimeException("错误的toDateTime参数类型：" + obj.getClass());
    }

    public static Time toTime(Object obj) {
        verification(obj != null, "toTime的参数不能为空。");
        if ((obj instanceof Time))
            return (Time) obj;
        if ((obj instanceof String))
            return Time.valueOf((String) obj);
        if ((obj instanceof Date))
            return Time.valueOf(new SimpleDateFormat("HH:mm:ss").format((Date) obj));
        throw new RuntimeException("错误的toTime参数类型：" + obj.getClass());
    }

    public static String toChineseNumber(Number value, boolean isCapital) {
        verification(value != null, "toChineseNumber的参数不能为空。");
        verification(isCapital, "目前不支持转换为小写的汉字数字！");
        if ((value instanceof BigDecimal)) {
            return NumberUtil.formatString((BigDecimal) value);
        }
        return NumberUtil.formatString(value.doubleValue());
    }

    public static String toChineseMoney(Number value) {
        verification(value != null, "toChineseMoney的参数不能为空。");
        String s = null;
        if ((value instanceof BigDecimal))
            s = NumberUtil.formatString((BigDecimal) value);
        else {
            s = NumberUtil.formatString(value.doubleValue());
        }
        return NumberUtil.toMoeny(s);
    }

    public static String ltrim(String value) {
        if (value == null)
            return null;
        if ("".equals(value))
            return "";
        int i = 0;
        while ((i < value.length()) && (value.charAt(i) <= ' '))
            i++;
        return value.substring(i);
    }

    public static String rtrim(String value) {
        if (value == null)
            return null;
        if ("".equals(value))
            return "";
        int i = value.length();
        while ((i > 0) && (value.charAt(i - 1) <= ' '))
            i--;
        return value.substring(0, i);
    }

    public static String lpad(int length, int number) {
        String f = "%0" + length + "d";
        return String.format(f, new Object[]{Integer.valueOf(number)});
    }

    public static String getExtOfFile(String path) {
        String str = getNameOfFile(path);
        if ((str == null) || ("".equals(str)))
            return null;
        return str.indexOf('.') != -1 ? str.substring(str.lastIndexOf('.') + 1, str.length()) : null;
    }

    public static String getPathOfFile(String path) {
        if ((path == null) || ("".equals(path)))
            return null;
        path = path.trim();
        if (path.indexOf('/') == -1)
            return null;
        return path.substring(0, path.lastIndexOf('/'));
    }

    public static String getNameOfFile(String path) {
        if ((path == null) || ("".equals(path)))
            return null;
        path = path.trim();
        if (path.indexOf('/') == -1)
            return path;
        return path.substring(path.lastIndexOf('/') + 1, path.length());
    }

    public static String getNameNoExtOfFile(String path) {
        String fileName = getNameOfFile(path);
        if ((fileName == null) || ("".equals(fileName)))
            return fileName;
        return fileName.indexOf('.') != -1 ? fileName.substring(0, fileName.lastIndexOf('.')) : fileName;
    }

    private static void verification(boolean isOK, String message) {
        if (!isOK) {
            RuntimeException ex = new RuntimeException(message);
            throw ex;
        }
    }

    public static boolean isLongNull(Long value) {
        return (value == null) || (value.intValue() == 0);
    }

    public static boolean isIntegerNull(Integer value) {
        return (value == null) || (value.intValue() == 0);
    }

    /**
     * 判断文件名是否带盘符，重新处理
     * @param fileName
     * @return
     */
    public static String getFileName(String fileName){
        //判断是否带有盘符信息
        // Check for Unix-style path
        int unixSep = fileName.lastIndexOf('/');
        // Check for Windows-style path
        int winSep = fileName.lastIndexOf('\\');
        // Cut off at latest possible point
        int pos = (winSep > unixSep ? winSep : unixSep);
        if (pos != -1)  {
            // Any sort of path separator found...
            fileName = fileName.substring(pos + 1);
        }
        //替换上传文件名字的特殊字符
        fileName = fileName.replace("=","").replace(",","").replace("&","");
        return fileName;
    }

    static class NumberUtil {
        private static String[] quantity = {"", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟"};

        private static String[] bigNumber = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};

        private static int c = 4;

        private static int d = 8;

        private static int e = 1;

        private static int f = 2;

        private static int g = 4;

        private static int h = 8;

        public static String formatString(double paramDouble) {
            return formatString(new DecimalFormat("#.##################################").format(paramDouble));
        }

        public static String formatString(int value) {
            return formatString(String.valueOf(value));
        }

        public static String formatString(BigDecimal value) {
            return formatString(new DecimalFormat("#.##################################").format(value));
        }

        public static String formatString(String value) {
            if ((value == null) || ("".equals(value))) {
                return null;
            }

            Double.valueOf(value);
            StringBuffer sb = new StringBuffer();
            if (value.charAt(0) == '-') {
                sb.append("负");
                value = value.substring(1);
            }

            String[] valueArray = value.split("[.]");
            if ((valueArray.length > 2) || (valueArray.length < 1)) {
                throw new RuntimeException("非法的数值格式：" + value);
            }
            sb.append(smallToBig(valueArray[0]));
            if (valueArray.length == 2) {
                sb.append("点");
                for (int k : valueArray[1].toCharArray())
                    sb.append(bigNumber[(k - 48)]);
            }
            return sb.toString();
        }

        private static String smallToBig(String value) {
            StringBuffer sb = new StringBuffer();
            int i = 0;
            for (int j = 0; j < value.length(); j++) {
                int k = value.length() - j - 1;
                String str = quantity[k];
                int m = value.charAt(j) - '0';
                if (m == 0) {
                    if (((str.equals("亿")) && ((i & g) > 0)) || ((str.equals("万")) && ((i & f) > 0))) {
                        sb.append(str);
                    }
                    if (((i & h) == 0) && (j == value.length() - 1))
                        sb.append(bigNumber[m]);
                    i |= e;
                } else {
                    if (((i & e) > 0) && ((i & h) > 0))
                        sb.append("零");
                    if (k >= d)
                        i |= g;
                    else if (k >= c)
                        i |= f;
                    i &= (e ^ 0xFFFFFFFF);
                    sb.append(bigNumber[m]);
                    sb.append(str);
                    i |= h;
                }
            }

            return sb.toString();
        }

        public static String toMoeny(String value) {
//			CommonUtil.a((value != null) && (!"".equals(value)), "传入的数值不能为空。");
            if (value.indexOf('点') >= 0) {
                String[] valueArray = value.split("点");
//				CommonUtil.a(valueArray.length == 2, "非法的数字字符串：" + value);
//				CommonUtil.a(valueArray[1].length() <= 2, "超出精度的金额数值：" + value);
                StringBuffer sb = new StringBuffer(valueArray[0]);
                sb.append("元");
                sb.append(valueArray[1].charAt(0));
                sb.append("角");
                if (valueArray[1].length() == 2) {
                    sb.append(valueArray[1].charAt(1));
                    sb.append("分");
                }
                return sb.toString();
            }
            return value + "元整";
        }
    }

    public static void main(String[] args) {
        System.out.println(NumberUtil.smallToBig("120"));
    }
}