package com.iformall.utils;

import com.google.gson.internal.LinkedTreeMap;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;

/**
 * Created by Stormeye on 2018/8/10.
 */
public class BeanUtils {

    /**
     * 如果是null，将返回字符串0
     *
     * @param param
     * @return
     */
    public static String ifNullTo0(String param) {
        if (param == null || param.equals("null")) {
            return "0";
        }
        return param;
    }

    public static Object getValue(Object obj, String pro) throws NoSuchMethodException {
        return getValue(obj, pro, null);
    }

    /**
     * 根据属性名称获取JavaBean中对应的属性值
     *
     * @param obj 对象
     * @param pro 对应属性名称
     * @param num 整型参数
     * @return 对象对应属性值
     */
    public static Object getValue(Object obj, String pro, Integer num) throws NoSuchMethodException {
        Class<?> clazz = obj.getClass();
        do {
            try {
                String methodName = "getSimpleRegionModel" + pro.substring(0, 1).toUpperCase() + pro.substring(1);
                Method method;
                if (!Objects.isNull(num)) {
                    method = clazz.getDeclaredMethod(methodName, Integer.class);
                    return method.invoke(obj, num);
                } else {
                    method = clazz.getDeclaredMethod(methodName);
                    return method.invoke(obj);
                }
            } catch (NoSuchMethodException e) {
                clazz = clazz.getSuperclass();
            } catch (InvocationTargetException | IllegalAccessException e) {
                e.printStackTrace();
            }
        } while (clazz != Object.class);
        throw new NoSuchMethodException("no such method name : " + "getSimpleRegionModel" + pro.substring(0, 1).toUpperCase() + pro.substring(1));
    }


    public static void transMap2Bean2(Map<String, Object> map, Object obj) {
        if (map == null || obj == null) {
            return;
        }
        try {
            org.apache.commons.beanutils.BeanUtils.populate(obj, map);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据key数组和value数组拼接json
     *
     * @param keys   key数组
     * @param values value数据
     * @return json
     * @throws Exception
     */
    public static String wrapToJsonByKeyValue(String[] keys, String[] values) throws Exception {
        StringBuilder stringBuilder = new StringBuilder();
        if (keys.length != values.length) {
            throw new Exception("长度不匹配，不能进行JSON格式的转换");
        }
        for (int i = 0; i < keys.length; i++) {
            stringBuilder.append("\"").append(keys[i]).append("\":\"").append(values[i]).append("\",");
        }
        return "{" + stringBuilder.substring(0, stringBuilder.length() - 1) + "}";
    }

    /**
     * Converts a JavaBean to a map
     *
     * @param bean JavaBean to convert
     * @return map converted
     * @throws IntrospectionException failed to get class fields
     * @throws IllegalAccessException failed to instant JavaBean
     * @throws InvocationTargetException failed to call setters
     */
    public static final Map<String, Object> toMap(Object bean)
            throws Exception {
        Map<String, Object> returnMap = new LinkedTreeMap();
        if (bean instanceof Map) {
            returnMap.putAll((Map<String, Object>)bean);
            return returnMap;
        }
        BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (int i = 0; i< propertyDescriptors.length; i++) {
            PropertyDescriptor descriptor = propertyDescriptors[i];
            String propertyName = descriptor.getName();
            if (!propertyName.equals("class")) {
                Method readMethod = descriptor.getReadMethod();
                Object result = readMethod.invoke(bean, new Object[0]);
                if (result != null) {
                    returnMap.put(propertyName, result);
                } else {
                    returnMap.put(propertyName, "");
                }
            }
        }
        return returnMap;
    }

    /**
     * Converts a JavaBean to a map
     *
     * @param bean JavaBean to convert
     * @return map converted
     * @throws IntrospectionException failed to get class fields
     * @throws IllegalAccessException failed to instant JavaBean
     * @throws InvocationTargetException failed to call setters
     */
    public static final Map<String, String> toStringMap(Object bean)
            throws Exception {
        Map<String, String> returnMap = new LinkedTreeMap();
        if (bean instanceof Map) {
            returnMap.putAll((Map<String, String>)bean);
            return returnMap;
        }
        BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (int i = 0; i< propertyDescriptors.length; i++) {
            PropertyDescriptor descriptor = propertyDescriptors[i];
            String propertyName = descriptor.getName();
            if (!propertyName.equals("class")) {
                Method readMethod = descriptor.getReadMethod();
                Object result = readMethod.invoke(bean, new Object[0]);
                if (result != null) {
                    returnMap.put(propertyName, String.valueOf(result));
                } else {
                    returnMap.put(propertyName, "");
                }
            }
        }
        return returnMap;
    }

}
