/**
 * Copyright 2008-2009. Chongqing Communications Industry Services Co.,Ltd Information Technology Branch. All rights reserved.
 * <a>http://www.crunii.com</a>
 */
package com.crunii.micro.common.utils;

import com.crunii.micro.common.dto.SSHHost;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import java.beans.PropertyDescriptor;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author 田平 create 2022-12-17 15:19:05
 */
public class BasePropCopyUtil {

	private static final List<Class<?>> BASE_PROP_TYPE = Arrays.asList(
			String.class,
			Date.class,
			BigDecimal.class
	);

	private static final List<String> BASE_FIELD_TYPE = Arrays.asList(
			"roles"
	);

	/**
	 * <pre>
	 * 		获取bean的基础属性的map,只获取非静态属性，非finally属性
	 * 		基础属性包含 BASE_PROP_TYPE
	 * 		原生属性 int, double, float, long, short, boolean, byte, char
	 * 		原生属性的包装类
	 * 	 	java.lang.Boolean
	 *  	java.lang.Character
	 *  	java.lang.Byte
	 *  	java.lang.Short
	 *  	java.lang.Integer
	 *  	java.lang.Long
	 *  	java.lang.Float
	 *  	java.lang.Double
	 * </pre>
	 *
	 * @param bean
	 * @return
	 */
	public static Map<String, Object> getBasePropsOfBean(Object bean) {
		Map<String, Object> props = new HashMap<>(16);
		copyBasePropsToMap(bean, props);
		return props;
	}

	/**
	 * <pre>
	 * 		获取bean的基础属性的map,只获取非静态属性，非finally属性
	 * 		基础属性包含 BASE_PROP_TYPE
	 * 		原生属性 int, double, float, long, short, boolean, byte, char， void
	 * 		原生属性的包装类
	 * 	 	java.lang.Boolean
	 *  	java.lang.Character
	 *  	java.lang.Byte
	 *  	java.lang.Short
	 *  	java.lang.Integer
	 *  	java.lang.Long
	 *  	java.lang.Float
	 *  	java.lang.Double
	 *  	java.lang.Void
	 * </pre>
	 *
	 * @param bean
	 * @param target
	 * @return
	 */
	public static void copyBasePropsToMap(Object bean, Map<String, Object> target) {
		if (bean != null && target != null) {
			BeanWrapper beanWrapper = new BeanWrapperImpl(bean);
			PropertyDescriptor[] descriptors = beanWrapper.getPropertyDescriptors();
			for (PropertyDescriptor descriptor : descriptors) {
				Class<?> type = descriptor.getPropertyType();
				String name = descriptor.getName();
				if (BASE_PROP_TYPE.contains(type) || type.isPrimitive() || isWarpPrimitive(type) || BASE_FIELD_TYPE.contains(name)) {
					target.put(descriptor.getName(), beanWrapper.getPropertyValue(descriptor.getName()));
				}
			}
		}
	}

	public static boolean isWarpPrimitive(Class<?> type) {
		try {
			return ((Class) (type.getField("TYPE").get(null))).isPrimitive();
		} catch (Exception e) {
			return false;
		}
	}

	public static void main(String[] args) {
		SSHHost host = new SSHHost();
		getBasePropsOfBean(host).forEach((k, v) -> {
			System.out.println(k + ":" + v);
		});
	}

}
