package com.pictc.utils;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Hashtable;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class MapUtils {
	
    public static enum MapType {
    	hashMap,Hashtable,Properties,LinkedHashMap,IdentityHashMap,
		TreeMap,WeakHashMap,ConcurrentHashMap
    }
    
    public static MapType parseMapType(Class<?> cls) {
    	if(Hashtable.class.equals(cls)) {
    		return MapType.Hashtable;
    	}else if(Properties.class.equals(cls)) {
    		return MapType.Properties;
    	}else if(LinkedHashMap.class.equals(cls)) {
    		return MapType.LinkedHashMap;
    	}else if(IdentityHashMap.class.equals(cls)) {
    		return MapType.IdentityHashMap;
    	}else if(TreeMap.class.equals(cls)) {
    		return MapType.TreeMap;
    	}else if(WeakHashMap.class.equals(cls)) {
    		return MapType.WeakHashMap;
    	}else if(ConcurrentHashMap.class.equals(cls)) {
    		return MapType.ConcurrentHashMap;
    	}else {
    		return MapType.hashMap;
    	}
    }
    
    
    @SuppressWarnings("unchecked")
	public static <K, V> Map<K,V> getMapNewInstance(MapType type) {
    	Map<K,V> result=null;
    	switch (type) {
		case Hashtable:
			result=CollectionUtils.newHashtable();
			break;
		case Properties:
			result=(Map<K, V>) CollectionUtils.newProperties();
			break;
		case LinkedHashMap:
			result=CollectionUtils.newLinkedHashMap();
			break;
		case IdentityHashMap:
			result=CollectionUtils.newIdentityHashMap();
			break;
		case TreeMap:
			result=CollectionUtils.newTreeMap();
			break;
		case WeakHashMap:
			result=CollectionUtils.newWeakHashMap();
			break;
		case ConcurrentHashMap:
			result=CollectionUtils.newConcurrentHashMap();
			break;
		default:
			result=CollectionUtils.newHashMap();
			break;
		}
		return result;
    }

	public static <K, V> Map<K,V> newInstance(Class<?> cls) {
		return getMapNewInstance(parseMapType(cls));
    }
	
	public static <K, V, R> Map<K,V> ofList(Collection<V> collections,TFunction<V, R> fn) {
		Map<K,V> map = CollectionUtils.newHashtable(); 
		Field field = LambdaUtils.getField(fn);
		for (V v : collections) {
			K k = BeanUtils.getFieldValue(field, v);
			map.put(k, v);
		}
		return map;
    }


}
