package org.springblade.openinterface.dianxin.util;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Map;

/**
 * @author lidexi
 * @date 2021/6/23 18:57
 */

public class FormString {
	/**
	 * 格式化对象为字符串，输出格式为 参数=值&参数=值，并对中文字符进行转义
	 * 支持的转换对象：Java基础数据类型、String、Data、Array、Map、Collection、自定义对象(不超过以上类型)
	 *
	 * @param
	 * @return 格式化后字符串
	 */
	public static String asForm(Object o) {
		StringBuilder json = new StringBuilder();
		asForm(json, o, 0);
		return json.toString();
	}

	private static void asForm(StringBuilder json, Object o, int level) {
		if (o == null) {
			json.append("");
		} else if (o instanceof String || o instanceof Boolean) {
			json.append(encode((String) o));
		} else if (o instanceof Integer || o instanceof Double || o instanceof Long || o instanceof Float
			|| o instanceof Short || o instanceof Byte || o instanceof BigDecimal) {
			json.append(o);
		} else if (o instanceof Date) {
			json.append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(o));
		} else if (o instanceof Array) {
			jsonArray(json, (Object[]) o, level);
		} else if (o instanceof Map) {
			jsonMap(json, (Map) o, level);
		} else if (o instanceof Collection) {
			jsonCollection(json, (Collection) o, level);
		} else {
			jsonObject(json, o, level);
		}
	}

	private static String encode(String str) {
		if (str == null)
			return "";
		try {
			return URLEncoder.encode(str, "utf-8");
		} catch (UnsupportedEncodingException e) {
			return str;
		}
	}

	private static void jsonCollection(StringBuilder json, Collection co, int level) {
		boolean isFirst = true;
		for (Object o : co) {
			if (isFirst) {
				isFirst = false;
			} else {
				json.append(',');
			}
			asForm(json, o, level + 1);
		}
	}

	private static void jsonArray(StringBuilder json, Object[] co, int level) {
		boolean isFirst = true;
		for (Object o : co) {
			if (isFirst) {
				isFirst = false;
			} else {
				json.append(',');
			}
			asForm(json, o, level + 1);
		}
	}

	private static void jsonMap(StringBuilder json, Map map, int level) {
		boolean isFirst = true;
		for (Object o : map.entrySet()) {
			Map.Entry e = (Map.Entry) o;
			if (e.getValue() == null)
				continue;
			if (isFirst) {
				isFirst = false;
			} else {
				json.append('&');
			}
			json.append(e.getKey()).append("=");
			asForm(json, e.getValue(), level + 1);
		}
	}

	private static String firstLower(String str) {
		char[] ca = str.toCharArray();
		if (ca[0] < 91)
			ca[0] += 32;
		return new String(ca);
	}

	private static void jsonObject(StringBuilder json, Object o, int level) {
		boolean isFirst = true;
		Method[] methods = o.getClass().getDeclaredMethods();
		for (Method m : methods) {
			String name = m.getName();
			if (!name.startsWith("get"))
				continue;
			Object value = null;
			try {
				value = m.invoke(o, null);
			} catch (Exception e) {
				e.printStackTrace();
				// log.warn(" fail to get value:",o.getClass(),m.getName(), e);
			}
			if (value == null)
				continue;
			name = firstLower(name.substring(3));
			if (isFirst) {
				isFirst = false;
			} else {
				json.append('&');
			}
			json.append(name).append("=");
			asForm(json, value, level + 1);
		}
	}
}
