package com.freemud.sdk.api.assortment.order.util;

import com.alibaba.fastjson.JSONObject;
import com.freemud.application.sdk.api.ordercenter.response.QueryOrderStateResp;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;

/**
 * All rights Reserved, Designed By www.freemud.cn
 *
 * @version V1.0
 * @Title: MapBeanConvertUtil
 * @Package com.freemud.base.util
 * @Description: Map和Bean互转
 * @author: jiaxin.liu
 * @date: 2017/5/16 10:44
 * @Copyright: 2017 www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目
 */
public class MapBeanConvertUtil {
    public final static char SIGN = '|';
    private PropertyDescriptor property;

    public static void transMap2BeanList(List<Map<String, Object>> mapList, List<QueryOrderStateResp> objList) {
        if (mapList.size() != objList.size()) {
            return;
        }

        for (int i = 0; i < mapList.size(); i++) {
            transMap2Bean(mapList.get(i), objList.get(i));
        }
    }

    /**
     * 按照ASCII 排序
     * @param obj 排序类
     * @return
     */
    public static String sortObjWithoutSign(Object obj) {
        Map<String, Object> stringObjectMap = transBean2Map(obj);
        return sortMapWithoutSign(stringObjectMap, SIGN, true);
    }

    public static String sortMapWithoutSign(Map<String, Object> params, char sign, boolean containSymbols) {
        if (CollectionUtils.isEmpty(params)) {
            return null;
        }
        params.remove("sign");
        String buff = "";
        try {
            List<Map.Entry<String, Object>> infoIds = new ArrayList<>(params.entrySet());
            // 对所有传入参数按照字段名的 ASCII 码从小到大排序（字典序）
            infoIds.sort(Comparator.comparing(o -> (o.getKey())));
            // 构造URL 键值对的格式
            StringBuilder buf = new StringBuilder();
            for (Map.Entry<String, Object> item : infoIds) {
                if (!StringUtils.isEmpty(item.getKey())) {
                    String key = item.getKey();
                    String val = null;
                    if (item.getValue() == null) {
                        continue;
                    } else {
                        val = String.valueOf(item.getValue());
                    }
                    buf.append(key).append(containSymbols ? "=" : "").append(val);
                    buf.append(sign);
                }

            }
            buff = buf.toString();
            if (buff.isEmpty() == false && containSymbols) {
                buff = buff.substring(0, buff.length() - 1);
            }
        } catch (Exception e) {

            return null;
        }
        return buff;
    }

    /**
     * Map --> Bean
     *
     * @param map
     * @param obj
     */
    public static void transMap2Bean(Map<String, Object> map, Object obj) {
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                if (map.containsKey(key)) {
                    Object value = map.get(key);
                    // 得到property对应的setter方法
                    Method setter = property.getWriteMethod();
                    setter.invoke(obj, value);
                }
            }
        } catch (Exception e) {
            System.out.println("transMap2Bean Error " + e);
        }
        return;
    }

    /**
     * Bean --> Map
     *
     * @param obj
     * @return
     */
    public static Map<String, Object> transBean2Map(Object obj) {

        if (obj == null) {
            return null;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                // 过滤class属性
                if (!key.equals("class")) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    map.put(key, value);
                }
            }
        } catch (Exception e) {
            System.out.println("transBean2Map Error " + e);
        }
        return map;
    }

    /**
     * @param obj
     * @param isboolean 为null或者为""的值是否不添加到map
     * @return
     */
    public static Map<String, Object> transBean2Map(Object obj, boolean isboolean) {

        if (obj == null) {
            return null;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                // 过滤class属性
                if (!key.equals("class")) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    if (getter != null) {
                        Object value = getter.invoke(obj);
                        if (isboolean && (value == null)) {
                            continue;
                        }
                        map.put(key, value);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    public static String sortDataByAcss(Map<String, Object> params, char sign) {
        StringBuilder paramsStr = new StringBuilder();
        Collection<String> keyset = params.keySet();
        List list = new ArrayList<String>(keyset);
        Collections.sort(list);
        for (int i = 0; i < list.size(); i++) {
            paramsStr.append(sign);
            paramsStr.append(params.get(list.get(i)));
        }
        if (paramsStr.length() > 0) {
            paramsStr.deleteCharAt(0);
        }
        return paramsStr.toString();
    }

    public static String sortDataByAcssForJson(Map<String, Object> params, char sign) {
        StringBuilder paramsStr = new StringBuilder();
        Collection<String> keyset = params.keySet();
        List list = new ArrayList<String>(keyset);
        Collections.sort(list);
        for (int i = 0; i < list.size(); i++) {
            Object obj = params.get(list.get(i));
            if (obj instanceof String || obj instanceof Integer || obj instanceof BigDecimal || obj instanceof Date
                    || obj instanceof Long || obj instanceof Short) {
                paramsStr.append(sign);
                paramsStr.append(params.get(list.get(i)));
            }
        }
        if (paramsStr.length() > 0) {
            paramsStr.deleteCharAt(0);
        }
        return paramsStr.toString();
    }

    public static String sortDataByASCII(Object object) {
        Map<String, Object> params = transBean2Map(object);
        StringBuilder paramsStr = new StringBuilder();
        Collection<String> keyset = params.keySet();
        List list = new ArrayList<String>(keyset);
        Collections.sort(list);
        for (int i = 0; i < list.size(); i++) {
            paramsStr.append(SIGN);
            paramsStr.append(params.get(list.get(i)));
        }
        if (paramsStr.length() > 0) {
            paramsStr.deleteCharAt(0);
        }
        return paramsStr.toString();
    }


    /**
     * Bean --> Map
     *
     * @param obj
     * @return
     */
    public static Map<String, String> transBeanStringMap(Object obj) {

        if (obj == null) {
            return null;
        }
        Map<String, String> map = new HashMap<String, String>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                // 过滤class属性
                if (!key.equals("class")) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    map.put(key, value != null ? value.toString() : null);
                }
            }
        } catch (Exception e) {
            System.out.println("transBean2Map Error " + e);
        }
        return map;
    }

    /**
     * @param isBasic 是否只有基础类型才转换。
     * @return
     */
    public static Map<String, String> transBeanStringMap(Object obj, boolean isBasic) {
        if (obj == null) {
            return null;
        }
        Map<String, String> map = new HashMap<String, String>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                // 过滤class属性
                if (!key.equals("class")) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    if (isBasic && value != null && (value instanceof String || value instanceof Integer || value instanceof BigDecimal || value instanceof Date
                            || value instanceof Long || value instanceof Short)) {
                        map.put(key, value.toString());
                    }
                }
            }
        } catch (Exception e) {
            System.out.println("transBean2Map Error " + e);
        }
        return map;
    }

    /**
     * Bean --> Map
     *
     * @param obj
     * @return
     */
    public static Map<String, String> transBean2StringMap(Object obj) {

        if (obj == null) {
            return null;
        }
        Map<String, String> map = new HashMap<String, String>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                // 过滤class属性
                if (!key.equals("class")) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    map.put(key, String.valueOf(value));
                }
            }
        } catch (Exception e) {
            System.out.println("transBean2Map Error " + e);
        }
        return map;
    }

    /**
     * 将bean转换为Map<String, String> value 为对象则转换为json
     *
     * @param obj
     * @return
     */
    public static Map<String, String> transBean2MapJson(Object obj) {
        if (obj == null) {
            return null;
        }
        Map<String, String> map = new HashMap<String, String>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                // 过滤class属性
                if (!key.equals("class")) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    if(value == null) {
                        continue;
                    }
                    if (value instanceof String || value instanceof Integer || value instanceof BigDecimal || value instanceof Date
                            || value instanceof Long || value instanceof Short) {
                        map.put(key, value.toString());
                    } else {
                        map.put(key, JSONObject.toJSONString(value));
                    }
                }
            }
        } catch (Exception e) {
            System.out.println("transBean2Map Error " + e);
        }
        return map;
    }

}
