package com.pictc.utils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.Getter;

/**
 * @Description TODO(这里用一句话描述这个类的作用)
 * @author zhangfucai
 * @Date 2022年11月7日 下午11:30:00
 * @version 1.0.0
 */
@Getter
public class TypeInfo {

	private Type type;
	
	private Class<?> klass;
	
	private Type[] generics;
	
	public TypeInfo(Type type) {
		super();
		this.type = type;
		if(type instanceof Class) {
			klass = (Class<?>)type;
			List<Type> types = CollectionUtils.newArrayList();
			addGenerics(types, klass.getGenericSuperclass());
			Type[] itypes = klass.getGenericInterfaces();
			if(itypes!=null) {
				for (int i = 0; i < itypes.length; i++) {
					addGenerics(types, itypes[i]);
				}
			}
			generics = ArrayUtils.ofCollection(types);
		}else if(type instanceof ParameterizedType) {
			ParameterizedType gtype = ((ParameterizedType)type);
			klass = (Class<?>) gtype.getRawType();
			generics = gtype.getActualTypeArguments();
		}
	}
	
	private void addGenerics(List<Type> types,Type stype) {
		if(stype!=null && stype instanceof ParameterizedType) {
			ParameterizedType gtype = ((ParameterizedType)stype);
			Type[] sgs = gtype.getActualTypeArguments();
			if(sgs!=null) {
				for (Type _t : sgs) {
					types.add(_t);
				}
			}
		}
	}
	
	public static TypeInfo valueOf(Type type) {
		return new TypeInfo(type);
	}

	public boolean isGenerics() {
		return generics!=null;
	}
	
	public Type getGenericType(int index) {
		if(!isGenerics()) {
			throw new RuntimeException("不是泛型，无法获取泛型类型");
		}
		return generics[index];
	}
	
	public Type getCollectionType() {
		if(!isGenerics()) {
			throw new RuntimeException("不是泛型，无法获取泛型类型");
		}
		return generics[0];
	}
	
	public boolean isArray() {
		return klass.isArray();
	}
	
	public boolean isInterface() {
		return klass.isInterface();
	}
	
	public boolean isPrimitive() {
		return ClassUtils.isPrimitive(klass);
	}
	
	public boolean isEnum() {
		return klass.isEnum();
	}
	
	public boolean isCollection() {
		return ClassUtils.isCollection(klass);
	}
	
	public boolean isList() {
		return ClassUtils.isList(klass);
	}
	
	public boolean isSet() {
		return ClassUtils.isSet(klass);
	}
	
	public boolean isMap() {
		return ClassUtils.isMap(klass);
	}
	
	public Class<?> getArrayType(){
		return klass.getComponentType();
	}
	
	public <T>Collection<T> newCollection(){
		return isList()?newList():newSet();
	}
	
	public <T>List<T> newList(){
		return ListUtils.getMapNewInstance(ListUtils.parseType(klass));
	}
	
	public <T>Set<T> newSet(){
		return SetUtils.getMapNewInstance(SetUtils.parseType(klass));
	}
	
	public <K,V>Map<K,V> newMap(){
		return MapUtils.getMapNewInstance(MapUtils.parseMapType(klass));
	}
	
	public String toString() {
		return String.format("Class:[%s],泛型：%s", klass.getName(),Arrays.toString(generics));
	}
}
