package com.bohuikeji.frame.module.admin.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bohuikeji.frame.module.admin.entity.vo.AddressVo;
import com.bohuikeji.frame.module.admin.exception.WebVerifiedException;
import com.google.common.base.CaseFormat;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.MessageFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.StringJoiner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符串处理工具类
 * @author 10552
 */
@Slf4j
public final class StringUtils extends org.apache.commons.lang3.StringUtils{
    public static DateTimeFormatter dataFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public static DateTimeFormatter dataTimeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public static DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("HH:mm:ss");
    public static DateTimeFormatter timeFormats = DateTimeFormatter.ofPattern("HH:mm");
    public static DecimalFormat df = new DecimalFormat("0.00");
    private static Pattern humpPattern = Pattern.compile("[A-Z]");
    public static String regEx="[\n`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。， 、？]";
    /**
     * 连字符命名转驼峰命名
     * @param underscore
     * @return
     */
    public static String underscoreToCamelCase(String underscore){
        String[] ss = underscore.split("-");
        if(ss.length ==1){
            return underscore;
        }

        StringBuffer sb = new StringBuffer();
        sb.append(ss[0]);
        for (int i = 1; i < ss.length; i++) {
            sb.append(upperFirstCase(ss[i]));
        }
        return sb.toString();
    }

    /**
     * 驼峰 转连字符
     * @param camelCase
     * @return
     */
    public static String toLine(String camelCase){
        Matcher matcher = humpPattern.matcher(camelCase);
        StringBuffer sb = new StringBuffer();
        while(matcher.find()){
            matcher.appendReplacement(sb, "-"+matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 驼峰转下划线
     * @param camelCase
     * @return
     */
    public static String toUnderline(String camelCase){
        return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, camelCase);
    }
    /**
     * 下划线转驼峰
     * @param underline
     * @return
     */
    public static String toCameCase(String underline){
        return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, underline);
    }
    /**
     * 首字母 转小写
     * @param str
     * @return
     */
    private static String lowerFirstCase(String str) {
        char[] chars = str.toCharArray();
        chars[0] += 32;
        return String.valueOf(chars);
    }

    /**
     * 首字母 转大写
     * @param str
     * @return
     */
    public static String upperFirstCase(String str) {
        char[] chars = str.toCharArray();
        chars[0] -= 32;
        return String.valueOf(chars);
    }

    /**
     * 判断是否为日期类型
     * @param str 满足格式yyyy-MM-dd
     * @return
     */
    public static boolean isValidDate(String str) {
        if (isEmpty(str)){
            return false;
        }
        try{
            LocalDate.parse(str,dataFormat);
        }
        catch (DateTimeParseException exception){
            return false;
        }
        return true;
    }
    /**
     * 判断是否为日期类型
     * @param str 满足格式yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static boolean isValidTime(String str) {
        if (isEmpty(str)){
            return false;
        }
        try{
            LocalDate.parse(str,dataTimeFormat);
        }
        catch (DateTimeParseException exception){
            return false;
        }
        return true;
    }

    public static String getParamsStr(String dataWay){
        String paramsStr="?startTime=###&endTime="+LocalDateTime.now().format(dataTimeFormat);
        LocalDate nowDate=LocalDate.now();
        switch (dataWay){
            case "day":
                paramsStr.replaceFirst("###",nowDate.atTime(0,0).format(dataTimeFormat));
                break;
            case "week":
                paramsStr.replaceFirst("###",nowDate.minusDays((nowDate.getDayOfWeek().getValue()-1)).format(StringUtils.dataFormat));
                break;
            case "month":
                paramsStr.replaceFirst("###",nowDate.minusDays((nowDate.getDayOfMonth()-1)).format(StringUtils.dataFormat));
                break;
            case "quarter":
                //计算季度，共四季度(1-3、4-6、7-9、10-12）
                int month=(int)(Math.floor(nowDate.getMonthValue()/3.1)*3)+1;
                paramsStr.replaceFirst("###",LocalDate.of(nowDate.getYear(),month,(month+1)%2==0?31:30).format(StringUtils.dataFormat));
                break;
            case  "year":
                paramsStr.replaceFirst("###",LocalDate.of(nowDate.getYear(),1,1).format(StringUtils.dataFormat));
                break;
                default:
                    log.error("无法识别的时间区间！");
                    /*try {
                        throw new Exception("无法识别的时间区间");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }*/
        }
        return paramsStr;
    }

    /**
     * 从时间段中提取时间
     * @param str
     * @return
     */
    public static String[] getDateGroupByStr(String str){
        String[] dateGroup=str.trim().split("至");
        if (dateGroup.length!=2)return null;
        if (!isValidDate(dateGroup[0].trim())){
            if(!isValidTime(dateGroup[0].trim())){
                return null;
            }
        }
        if (!isValidDate(dateGroup[1].trim())){
            if(!isValidTime(dateGroup[1].trim())){
                return null;
            }
        }
        return dateGroup;
    }

    /**
     * 判断字符串是否是数字类型
     * @param str
     * @return
     */
    public static boolean isBigDecimal(String str) {
        if (str == null || str.trim().length() == 0) {
            return false;
        }
        char[] chars = str.toCharArray();
        int sz = chars.length;
        int i = (chars[0] == '-') ? 1 : 0;
        if (i == sz){
            return false;
        }
        if (chars[i] == '.'){
            //除了负号，第一位不能为'小数点'
            return false;
        }

        boolean radixPoint = false;
        for (; i < sz; i++) {
            if (chars[i] == '.') {
                if (radixPoint) {
                    return false;
                }
                radixPoint = true;
            } else if (!(chars[i] >= '0' && chars[i] <= '9')) {
                return false;
            }
        }
        return true;
    }
    public static boolean isPrice(String str) {
        if("0".equals(str)){
            return false;
        }
        Pattern pattern = Pattern.compile("^(([0-9]|([1-9][0-9]{0,9}))((\\.[0-9]{1,2})?))$"); // 判断小数点后2位的数字的正则表达式
        Matcher match = pattern.matcher(str);
        return match.matches();
    }

    /**
     * 转换String为目标对象格式
     * @param str 字符串
     * @param classz 对象格式
     * @return
     */
    public static Object strtoPojo(String str,Class classz){
        if (StringUtils.isBlank(str)){
            //log.warn("类型转换失败，字符串[{}]，为空或，无法识别，设置属性为null，目标类型[{}]",str,classz);
            return null;
        }
        if(classz==LocalDateTime.class){
            if (!isValidTime(str)){
                throw new WebVerifiedException("时间日期格式错误，无法识别["+str+"]");
            }
            return LocalDateTime.parse(str,dataTimeFormat);
        }
        if (classz==LocalDate.class){
            if (!isValidDate(str)){
                throw new WebVerifiedException("日期格式错误，无法识别["+str+"]");
            }
            return LocalDate.parse(str,dataFormat);
        }
        if (classz== LocalTime.class){
            if (!isValidDate(str)){
                throw new WebVerifiedException("时间格式错误，无法识别["+str+"]");
            }
            return LocalTime.parse(str,dataFormat);
        }
        if(classz==Integer.class){
            Integer integer=null;
            integer=Integer.valueOf(str);
            if(integer==null){
                throw new WebVerifiedException("数字格式错误，无法识别["+str+"]");
            }
            return integer;
        }
        if(classz==Double.class){
            Double d=null;
            d=Double.parseDouble(str);
            if(d==null){
                throw new WebVerifiedException("数值类型格式错误，无法识别【"+str+"】");
            }
            return d;
        }
        if(classz==Float.class){
            Float f=null;
            f=Float.parseFloat(str);
            if(f==null){
                throw new WebVerifiedException("数值类型格式错误，无法识别【"+str+"】");
            }
            return f;
        }
        if(classz==Long.class){
            Long l=null;
            l=Long.parseLong(str);
            if(l==null){
                throw new WebVerifiedException("数值类型格式错误，无法识别【"+str+"】");
            }
            return l;
        }
        if(classz==Boolean.class){
            Boolean b=null;
            b=Boolean.parseBoolean(str);
            if(b==null){
                throw new WebVerifiedException("逻辑类型格式错误，无法识别【"+str+"】");
            }
            return b;

        }
        if(classz== BigDecimal.class){
            if(!isBigDecimal(str)){
                throw new WebVerifiedException("金额类型格式错误，无法识别【"+str+"】");
            }
            return new BigDecimal(str);
        }
        if(classz== AddressVo.class){
            JSONObject address=JSON.parseObject(str);
            JSONObject location=address.getJSONObject("location");
            AddressVo advo;
            //坐标系为空，使用地理编码解析
            if(location==null){
                advo= MapUtils.getAddressGeo(address.getString("address"));
            }
            //有坐标系使用逆地理编码解析
            else{
                advo=MapUtils.getAddressReGeo(location.getString("lng")+","+location.getString("lat"));
                advo.setAddress(address.getString("address"));
            }
            return advo;
        }
        return str;
    }

    /**
     * 格式化字符串
     * @param str
     * @param args
     * @return
     */
    public static String formatStr(String str,Object... args){
        for(int i=0;i<args.length;i++){
            args[i]=String.valueOf(args[i]);
        }
        return MessageFormat.format(str,args);
    }

    /**
     * 正则校验是否为URL格式
     * @param str
     * @return
     */
    public static boolean isURL(String str){
        str = str.toLowerCase();
        String regex = "^((https|http)?://)"
        + "?(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?"
                + "(([0-9]{1,3}\\.){3}[0-9]{1,3}" // IP形式的URL- 例如：199.194.52.184
                + "|" // 允许IP和DOMAIN(域名)
                + "([0-9a-z_!~*'()-]+\\.)*" // 域名- www.
                + "([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\\." // 二级域名
                + "[a-z]{2,6})" // first level domain- .com or .museum
                + "(:[0-9]{1,5})?" // 端口号最大为65535,5位数
                + "((/?)|" // a slash isn't required if there is no file name
                + "(/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?)$";
        return str.matches(regex);
    }

    /**
     * 手机号码正则
     */
    private static final Pattern PHONE_REG = Pattern.compile("1[3456789]\\d{9}");
    private static final Pattern NUM_REG=Pattern.compile("\\d+");

    /**
     * 提取字符串中符合条件的手机号
     * @param str 待识别的字符串
     * @return 返回手机号码，如有多个则用;号分割
     */
    public static String strGetPhone(String str) {
        Matcher m = PHONE_REG.matcher(str);
        StringJoiner joiner = new StringJoiner(";");
        while (m.find()) {
            joiner.add(m.group());
        }
        return joiner.toString();
    }

    /**
     * 获取字符串中的所有数字
     * @param str
     * @return
     */
    public static String strGetNum(String str) {
        Matcher m = NUM_REG.matcher(str);
        StringJoiner joiner = new StringJoiner(";");
        while (m.find()){
            joiner.add(m.group());
        }
        return joiner.toString();
    }

    /**
     * 是为全部为中文
     * @param str
     * @return
     */
    public static boolean isChinese(String str) {
        String regEx = "^[\u4E00-\u9FA5]{2,6}$";
        Pattern pat = Pattern.compile(regEx);
        Matcher matcher = pat.matcher(str);
        boolean flg = false;
        if (matcher.find()) {
            flg = true;
        }
        return flg;
    }

    @Test
    public void test(){
        String str="明天/8:00~8:30";
        System.out.println(strGetNum(str));
    }
}
