package com.muchinfo.mtp3common.utils;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.*;

public class CommonUtil {
    private static final Logger logger = LoggerFactory.getLogger(CommonUtil.class);
    /***
     * 获得ip地址
     * @param request
     * @return
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ipAddress = null;
        ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null || ipAddress.length() == 0
                || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0
                || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0
                || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if ("127.0.0.1".equals(ipAddress)) {
                // 根据网卡取本机配置的IP
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                ipAddress = inet.getHostAddress();
            }
        }

        // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()=15
            if (ipAddress.indexOf(",") > 0) {
                ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
            }
        }
        return ipAddress;
    }

    /***
     * 生成随机数
     * @param len 长度
     */
    public static String Random(int len)
    {
        String num ;
        java.util.Random r = new java.util.Random();
        while(true){
            int i=r.nextInt(99999999);
            if(i<0)i=-i;
            num = String.valueOf(i);
            if(num.length()<len){
                continue;
            }
            if(num.length()>=len){
                num = num.substring(0,len);
                break;
            }
        }
        return num;
    }


    /***
     * 取得项目根目录的绝对路径
     * @return
     */
    public static String getRootPath(String path , String filename) {
        String classPath = path ;
        String rootPath  = "";
        //windows下
        if("\\".equals(File.separator)){
            rootPath  = classPath.substring(1,classPath.indexOf("/WEB-INF/classes"));
            if( StringUtils.isNotBlank( filename ) )
                rootPath = rootPath + filename;
            rootPath = rootPath.replace("/", "\\");
        }
        //linux下
        if("/".equals(File.separator)){
            rootPath  = classPath.substring(0,classPath.indexOf("/WEB-INF/classes"));
            if( StringUtils.isNotBlank( filename ) )
                rootPath = rootPath + filename;
            rootPath = rootPath.replace("\\", "/");
        }
        return rootPath;
    }

    /**
     * 获得字符串字节编码长度
     *
     * @Description
     * @param targetStr原字符
     * @param charsetName字符编码
     * @return
     * @ReturnType int
     * @author jiangc
     * @Created 2014 2014-2-28上午10:15:33
     */
    public static int getStrLenByByte(String targetStr, String charsetName) {
        byte[] a = null;
        try {
            if (charsetName == null || "".equals(charsetName)) {
                a = targetStr.getBytes();
            } else {
                a = targetStr.getBytes(charsetName);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return a != null ? a.length : 0;
    }

    /**
     * 按字节截取字符串
     *
     * @Description
     * @param targetStr原字符
     * @param startIndex开始位置
     * @param subLength截取长度
     * @param charsetName字符编码
     * @return
     * @ReturnType String
     * @author jiangc
     * @Created 2014 2014-2-28上午10:11:48
     */
    public static String subStrByByteLength(String targetStr, int startIndex,
                                            int subLength, String charsetName) {

        return substrbyte(targetStr, startIndex, startIndex + subLength,
                charsetName);

    }

    /**
     * 按字节格式字符串
     *
     * @Description
     * @param targetStr
     *            原字符
     * @param strLength
     *            指定总长度
     * @param fillStr
     *            填充字符
     * @return
     * @ReturnType String
     * @author jiangc
     * @Created 2014 2014-2-28上午09:39:42
     */
    public static String formatText(String targetStr, int strLength,
                                    String fillStr) {
        int curLength = targetStr.getBytes().length;
        if (targetStr != null && curLength > strLength)
            targetStr = subStringByte(targetStr, strLength);
        String newString = "";
        int cutLength = strLength - targetStr.getBytes().length;
        for (int i = 0; i < cutLength; i++)
            newString += fillStr;
        return targetStr + newString;
    }

    /**
     * 按字节格式字符串
     *
     * @Description
     * @param targetStr
     *            原字符
     * @param strLength
     *            指定总长度
     * @param fillStr
     *            填充字符
     * @return
     * @ReturnType String
     * @author jiangc
     * @Created 2014 2014-2-28上午09:39:42
     */
    public static String formatTextLeftFill(String targetStr, int strLength,
                                            String fillStr) {
        int curLength = targetStr.getBytes().length;
        if (targetStr != null && curLength > strLength)
            targetStr = subStringByte(targetStr, strLength);
        String newString = "";
        int cutLength = strLength - targetStr.getBytes().length;
        for (int i = 0; i < cutLength; i++)
            newString += fillStr;
        return newString+targetStr;
    }

    /**
     * 按字节截取指定长度的字符
     *
     * @Description
     * @param targetStr
     * @param strLength
     * @return
     * @ReturnType String
     * @author jiangc
     * @Created 2014 2014-2-28上午09:41:56
     */
    public static String subStringByte(String targetStr, int strLength) {

        while (targetStr.getBytes().length > strLength)
            targetStr = targetStr.substring(0, targetStr.length() - 1);
        return targetStr;
    }

    public static String substrbyte(String body, int start, int end,
                                    String charset) {
        int j = 0;
        byte[] temp = null;
        byte[] origin = null;
        String ret = "";
        try {
            if (charset == null || "".equals(charset)) {
                origin = body.getBytes();
            } else {
                origin = body.getBytes(charset);
            }
            temp = new byte[end - start];

            for (int i = start; i < end; i++) {
                temp[j] = origin[i];
                j++;
                // System.out.println("i:"+i + "  j:"+j);
            }
            if (charset == null || "".equals(charset)) {
                ret = new String(temp);
            } else {
                ret = new String(temp, charset);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return "";
        }
        // edit by jc 20140819 去空格
        return ret != null ? ret.trim() : "";
    }

    public static String formatLeftNull_byte(String value, int length) {
        value = value != null ? value : "";
        byte[] origin = null;
        try {
            origin = value.getBytes("GBK");

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return "";
        }
        String zero = "";
        // edit by jc 20140818 不空格问题（长度足够或者超过了指定长度）
        if (length - origin.length > 0) {
            zero = String.format("%-" + (length - origin.length) + "s", " ");
            return zero + value;
        } else if (length - origin.length == 0) {
            return value;
        } else {
            return subStrByByteLength(value, 0, length, "GBK");
        }
        // return zero+value;
    }

    public static String formatRightNull_byte(String value, int length) {
        value = value != null ? value : "";
        byte[] origin = null;
        try {
            origin = value.getBytes("GBK");

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return "";
        }
        String zero = "";
        // edit by jc 20140818 不空格问题（长度足够或者超过了指定长度）
        if (length - origin.length > 0) {
            zero = String.format("%-" + (length - origin.length) + "s", " ");
            return value + zero;
        } else if (length - origin.length == 0) {
            return value;
        } else {
            return subStrByByteLength(value, 0, length, "GBK");
        }

    }


    /**
     * Object转String
     *
     * @Description
     * @param obj
     * @return
     * @ReturnType String
     * @author jiangc
     * @Created 2014 2014-3-25上午10:47:42
     */
    public static String getStringValue(Object obj) {
        String value = obj != null ? String.valueOf(obj) : "";

        return value;
    }

    /**
     * Object转int
     *
     * @Description
     * @param obj
     * @return
     * @ReturnType String
     * @author jiangc
     * @Created 2014 2014-3-25上午10:47:42
     */
    public static int getIntValue(Object obj) {
        String value = obj != null ? String.valueOf(obj) : "";

        return (value != null && !"".equals(value)) ? Integer.parseInt(value)
                : 0;
    }

    /**
     * Object转Double
     *
     * @Description
     * @param obj
     * @return
     * @ReturnType String
     * @author jiangc
     * @Created 2014 2014-3-25上午10:47:42
     */
    public static double getDoubleValue(Object obj) {
        String value = obj != null ? String.valueOf(obj) : "";

        return (value != null && !"".equals(value)) ? Double.parseDouble(value)
                : 0.0;
    }

    /**
     * Object转Date
     *
     * @Description
     * @param obj
     * @return
     * @ReturnType String
     * @author jiangc
     * @Created 2014 2014-3-25上午10:47:42
     */
    public static Date getDateTimeValue(Object obj) {
        String value = obj != null ? String.valueOf(obj) : "";
        Date date = null;
        try {
            date = value != null ? DateTimeUtils.parseDate(value, "yyyy-MM-dd HH:mm:ss") : null;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 打印异常
     *
     * @Description
     * @param e
     * @ReturnType void
     * @author jiangc
     * @Created 2014 2014-4-10下午03:59:17
     */
    public static void printErrLog(Exception e) {
        if (e != null) {
            logger.info(" Exception ERROR:" + e.getMessage());
            StackTraceElement[] sArr = e.getStackTrace();
            String err = "";
            if (sArr != null) {
                for (int i = 0; i < sArr.length - 1; i++) {
                    StackTraceElement s = sArr[i];
                    err += "\r\n#Class=" + s.getClassName() + ";File="
                            + s.getFileName() + ";Line=" + s.getLineNumber()
                            + ";Method=" + s.getMethodName() + "";
                }
                logger.info(err);
            }
            // e.printStackTrace();

        }
    }

    /**
     * double相 加
     *
     * @param v1
     * @param v2
     * @return
     */
    public static double add(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }

    /**
     * double相 减
     *
     * @param v1
     * @param v2
     * @return
     */
    public static double subtract(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }

    /**
     * 右边补空格
     * @Description
     * @param value
     * @param length
     * @return
     * @ReturnType String
     * @author jiangc
     * @Created 2014 2014-2-26下午05:41:31
     */
    public static String formatRightNull(String value,int length){
        value=value!=null?value:"";
        String zero=String.format("%-"+(length-value.length())+"s"," ");

        return value+zero;
    }

    /**
     * 左边补空格
     * @Description
     * @param value
     * @param length
     * @return
     * @ReturnType String
     * @author jiangc
     * @Created 2014 2014-2-26下午05:42:01
     */
    public static String formatLeftNull(String value,int length){
        value=value!=null?value:"";
        String zero=String.format("%-"+(length-value.length())+"s"," ");

        return zero+value;
    }

    public static String getMapValue(Map<String, Object> map, String key) {
        String obj = "";
        if (map != null) {
            obj = map.get(key) != null ? map.get(key).toString() : "";
        }

        return obj.trim();
    }

    public static int getMapIntValue(Map<String, Object> map, String key) {
        int obj = 0;
        if (map != null) {
            obj = map.get(key) != null ? Integer.parseInt(map.get(key)
                    .toString()) : 0;
        }

        return obj;
    }

    public static double getMapDoubleValue(Map<String, Object> map, String key) {
        double obj = 0.0;
        if (map != null) {
            obj = map.get(key) != null ? Double.parseDouble(map.get(key)
                    .toString()) : 0;
        }

        return obj;
    }

    /**
     *
     * @param list list元素的属性可以是数字(byte,short,int,long,float,double等,支持正数,负数,0),char,String,java.util.Date
     * @param isAsc true 升序,false降序
     * @param sortnameArr list元素的属性名称
     */
    public static <E> void sort(List<E> list, final boolean isAsc, final String... sortnameArr){
        Collections.sort(list, new Comparator<E>(){
            public int compare(E a, E b){
                int ret = 0;
                try{
                    for(int i=0; i<sortnameArr.length; i++){
                        ret = compareObject(sortnameArr[i], isAsc, a, b);
                        if(0 != ret){
                            break;
                        }
                    }
                }catch(Exception e){
                    e.printStackTrace();
                }

                return ret;
            }
        });
    }

    /**
     *
     * @param list list元素的属性可以是数字(byte,short,int,long,float,double等,支持正数,负数,0),char,String,java.util.Date
     * @param sortnameArr 参数数组
     * @param typeArr 每个属性对应的升降序数组,true升序,false降序
     */
    public static <E> void sort(List<E> list, final String[] sortnameArr, final boolean[] typeArr){
        if(sortnameArr.length != typeArr.length){
            throw new RuntimeException("属性数组元素和升序降序数组元素个数不相等");
        }
        Collections.sort(list, new Comparator<E>(){
            public int compare(E a, E b){
                int ret = 0;
                try{
                    for(int i=0; i<sortnameArr.length; i++){
                        ret = compareObject(sortnameArr[i], typeArr[i], a, b);
                        if(0 != ret){
                            break;
                        }
                    }
                }catch(Exception e){
                    e.printStackTrace();
                }
                return ret;
            }
        });
    }

    /**
     * 对两个对象按照指定属性名称进行排序
     * @param sortname 属性名称
     * @param isAsc
     * @param a
     * @param b
     * @return
     * @throws Exception
     */
    private static <E> int compareObject(final String sortname, final boolean isAsc, E a, E b) throws Exception{
        int ret = 0;
        Object value1 = forceGetFieldValue(a, sortname);
        Object value2 = forceGetFieldValue(b, sortname);
        String str1 = value1.toString();
        String str2 = value2.toString();
        if(value1 instanceof Number && value2 instanceof Number){
            int maxlen = Math.max(str1.length(), str2.length());
            str1 = addZero2Str((Number)value1, maxlen);
            str2 = addZero2Str((Number)value2, maxlen);
        }else if(value1 instanceof Date && value2 instanceof Date){
            long time1 = ((Date)value1).getTime();
            long time2 = ((Date)value2).getTime();
            int maxlen = Long.toString(Math.max(time1, time2)).length();
            str1 = addZero2Str(time1, maxlen);
            str2 = addZero2Str(time2, maxlen);
        }
        if(isAsc){
            ret = str1.compareTo(str2);
        }else{
            ret = str2.compareTo(str1);
        }
        return ret;
    }

    public static String addZero2Str(Number numObj, int length){
        NumberFormat nf = NumberFormat.getInstance();
        nf.setGroupingUsed(false); //设置是否使用分组
        nf.setMaximumIntegerDigits(length); //设置最大整数
        nf.setMinimumIntegerDigits(length);	//设置最小整数
        return nf.format(numObj);
    }

    @SuppressWarnings("rawtypes")
    public static Object forceGetFieldValue(Object obj, String fieldName) throws Exception{
        Field field = null;
        try{
            field = obj.getClass().getDeclaredField(fieldName);
        }catch(Exception e){

        }
        if (field == null)
        {
            Class superclass = obj.getClass().getSuperclass();
            while (superclass != null && field == null)
            {
                try{
                    field = superclass.getDeclaredField(fieldName);
                }catch(Exception e){

                }
                superclass = superclass.getSuperclass();
            }
        }
        Object object = null;
        boolean accessible = field == null? true: field.isAccessible();
        if(!accessible){
            //如果是private,protected修饰的属性,需要修改为可以访问的
            field.setAccessible(true);
            //首字母转大写
            char[] columnfields = fieldName.toCharArray();
            columnfields[0] -= 32;
            String getMethod = "get"+String.valueOf(columnfields);
            Method objMethod = obj.getClass().getMethod(getMethod);
            object = objMethod.invoke(obj);
//			object = field.get(obj);
            //还原private,protected属性的访问性质
            field.setAccessible(accessible);
            return object;
        }
        object = field == null ? null : field.get(obj);
        return object;
    }

    public static String addZero(String orgStr, int len) {
        if (orgStr != null && !"".equals(orgStr)) {
            int orgStrLen = orgStr.length();
            for (int i = 0; i < len - orgStrLen; i++) {
                orgStr = "0" + orgStr;
            }
        }
        return orgStr;
    }

    public static String getUuid() {
        String[] chars = new String[]{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q",
                "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q",
                "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
        StringBuffer shortBuffer = new StringBuffer();
        String uuid = UUID.randomUUID().toString().replace("-", "");
        for (int i = 0; i < 8; i++) {
            String str = uuid.substring(i * 4, i * 4 + 4);
            int x = Integer.parseInt(str, 16);
            // % chars 数组的长度16进制
            shortBuffer.append(chars[x % 0X3E]);
        }
        return shortBuffer.toString();
    }

    //仅数字
    public static String getUuid2() {
        String[] chars = new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
        StringBuffer shortBuffer = new StringBuffer();
        String uuid = UUID.randomUUID().toString().replace("-", "");
        for (int i = 0; i < 8; i++) {
            String str = uuid.substring(i * 4, i * 4 + 4);
            int x = Integer.parseInt(str, 16);
            // % chars 数组的长度16进制
            shortBuffer.append(chars[x % 0XA]);
        }
        return shortBuffer.toString();
    }

    //隐藏手机号 131****1111
    public static String unViewMobile(String str){
        // 兼容国外手机号处理
        // #6686 【交易中心-管理端】客户端注册时手机号加了地区号的情况下交易商名称没有完整显示手机尾号
        if(str == null || StringUtils.isBlank(str) || str.length() < 11){
            return str;
        }else{
            // 超过11位时，统一前3+****+后4
            StringBuffer sb = new StringBuffer();
            sb.append(str.substring(0,3));
            sb.append("****");
            sb.append(str.substring(str.length() -4));
            return sb.toString();
        }
    }
}
