package com.tzy.common.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tzy.common.annotation.Property;
import com.tzy.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.commons.beanutils.converters.DateConverter;
import org.yaml.snakeyaml.util.UriEncoder;

import java.lang.reflect.Field;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Bean
 */
@Slf4j
public class BeanUtil {

//    public static String regSpecial = "[`~!@#$%^*()+=|{}':;',\\[\\]./?~！@#￥%……*（）_——+|{}【】‘；：”“’。，、？ ]";
    public static String regSpecial = "[`~!@#$%^&*()+=|{}':;',\n \\[\\].<>/?~！@#￥%……&*（）_——+|{}【】‘；：”“’。，、？]";
    public static String regSpecial1 = "[`~!@#$%^&*()+=|{}';',\\[\\]/?~！@#￥%……&*（）_——+|{}【】‘；”“’。，、？ ]";
    public static BeanUtilsBean beanUtilsBean;
    static{
        //处理时间格式
        DateConverter dateConverter = new DateConverter();
        //设置日期格式
        dateConverter.setPatterns(new String[]{"yyyy-MM-dd","yyyy-MM-dd HH:mm:ss"});
        //注册格式
        ConvertUtilsBean convertUtilsBean=new ConvertUtilsBean();
        convertUtilsBean.register(dateConverter,Date.class);
        beanUtilsBean = new BeanUtilsBean(convertUtilsBean, new PropertyUtilsBean());
    }

    /**
     * 整理JSON key 首字母大写转小写
     * 有特殊字符进行清除操作
     * @param object json
     * @param clearSpecial 是否清除特殊字符
     * @return
     */
    public static JSONObject covertObject(JSONObject object, boolean clearSpecial) {
        JSONObject newObject = new JSONObject();
        Set<String> set = object.keySet();
        for (String key : set) {
            Object value = object.get(key);
            if(clearSpecial){
                key = checkChar(regSpecial,key);
            }
            String keyOne = key.substring(0,1).toLowerCase();
            String keylast = key.substring(1);
            key = keyOne+keylast;
            Class<?> aClass = value.getClass();
            String name = aClass.getName();
            if(name.contains("net.sf.json.JSONObject") && null != value){
                JSONObject json = (JSONObject) value;
                value = covertObject(json,clearSpecial);
            }
            if(name.contains("net.sf.json.JSONArray") && null != value){
                JSONArray json = (JSONArray) value;
                JSONArray jsonArray = new JSONArray();
                for(int i= 0 ; i< json.size() ; i++){
                    Object jsonObject = json.get(i);
                    if(null != jsonObject && jsonObject.getClass().getName().contains("net.sf.json.JSONObject")){
                        jsonArray.add(covertObject(json.getJSONObject(i),clearSpecial));
                    }else {
                        jsonArray.add(jsonObject);
                    }
                }
                value = jsonArray;
            }
            newObject.put(key, value);
        }
        return newObject;
    }

    /**
     *
     * @param pattern 正则表达式
     * @param str   内容
     * @return
     */
    public static String checkChar(String pattern ,String str){
        try {
            Pattern p = Pattern.compile(pattern);
            Matcher m = p.matcher(str);
            str = m.replaceAll("").trim();
        }catch (Exception e){
            e.printStackTrace();
        }
        return str;
    }
    /**
     * 参数 排序 组合
     * @param map
     * @return
     */
    public static String param2str(Map map){
        if(null == map ) map = new HashMap();
        Set set = map.entrySet();
        StringBuffer signA = new StringBuffer();
        set.stream().forEach( smap -> {
            signA.append("&").append(smap);
        } );
        return signA.toString().substring(1,signA.length());
    }

    /**
     * 参数 排序 组合
     * @param map
     * @return
     */
    public static String map2str(Map map){
        if(null == map ) map = new HashMap();
        Set set = map.entrySet();
        StringBuffer signA = new StringBuffer();
        set.stream().forEach( smap -> {
            signA.append("&").append(smap);
        } );
        return signA.toString().substring(1,signA.length());
    }
    /**
     * 参数 排序 组合
     * @param str
     * @return
     */
    public static Map str2Map(String str){
        Map map = new TreeMap();
        if(StringUtils.isEmpty(str) ) return map;
        if(str.indexOf("=") == -1 ) return map;
        try {
            String[] strs = str.split("&");
            for (String s : strs) {
                if (StringUtils.isNotEmpty(s)) {
                    String key = s.substring(0, s.indexOf("="));
                    String value = s.substring(s.indexOf("=") + 1);
                    map.put(key, UriEncoder.decode(value));
                    log.info(key + " >> {}", value);
                }
            }
            return map;
        }catch (Exception e){
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 格式化 url 参数 javabean 转 key=value&key=value...形式
     * @param obj javabean
     */
    public static String getFormatParam(Object obj){
        try {
            StringBuffer stb = new StringBuffer();
            if(null != obj) {
                for (Field field : obj.getClass().getDeclaredFields()) {
                    field.setAccessible(true);
                    String defaultName = "";
                    String fieldType = "";
                    Property property = field.getAnnotation(Property.class);
                    if (null != property) {
                        defaultName = property.defaultName();
                        fieldType = property.fieldType();
                    }
                    System.out.println(defaultName);
                    if (null != field.get(obj) && StringUtils.isNotEmpty(fieldType) && "field".equals(fieldType)) {
                        if (!"".equals(field.get(obj)) && "java.lang.String".contains(field.getType().getName())) {
                            stb.append(StringUtils.isEmpty(defaultName) ? field.getName() : defaultName)
                                    .append("=")
                                    .append(field.get(obj))
                                    .append("&")
                            ;
                        } else if (!"java.lang.String".contains(field.getType().getName())) {
                            stb.append(StringUtils.isEmpty(defaultName) ? field.getName() : defaultName)
                                    .append("=")
                                    .append(field.get(obj))
                                    .append("&")
                            ;
                        }
                    }
                    if (null != field.get(obj) && StringUtils.isNotEmpty(fieldType) && "class".equals(fieldType)) {
                        Object o = field.get(obj);
                        String formatParam = "&" + getFormatParam(o);
                        if (StringUtils.isNotEmpty(formatParam))
                            formatParam = formatParam.replaceAll("&", "&" + defaultName + ".");
                        stb.append(formatParam).append("&");
                    }
                    if (null != field.get(obj) && StringUtils.isNotEmpty(fieldType) && "map".equals(fieldType)) {
                        Map<String, Object> map = (Map) field.get(obj);
                        map.forEach((key, value) -> {
                            stb.append(key).append("=").append(value).append("&");
                        });
                    }
                }
                String ret = stb.toString();
                if(StringUtils.isNotEmpty(ret)){
                    ret = ret.substring(0, ret.length() - 1).replaceAll("&&", "&");
                }
                return ret;
            }
        } catch (Exception e) {
            System.out.println("transBean2Map Error " + e);
            e.printStackTrace();
        }
        return null;
    }


    public static void checkFormat(Object object){
        try {
            Class<?> clazz = object.getClass();
            for (Field field : clazz.getDeclaredFields()) {
                field.setAccessible(true);
                String fieldName = field.getName();
                Object value = field.get(object);

            }
        }catch (IllegalAccessException ie){
            ie.printStackTrace();
        }
    }

    /**
     * 带 Accessors 注解会无法赋值
     * @param bean
     * @param properties
     */
    public static void populate(Object bean, Map<String,Object> properties){
        try {
            //封装数据
            beanUtilsBean.populate(bean, properties);
        } catch (Exception e) {
            throw new ServiceException("数据异常!!!");
        }
    }

    public static void main(String[] args) {
    }


}
