package com.pictc.utils;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class SetUtils {

    public static enum SetType{
    	HashSet,TreeSet,LinkedHashSet,ConcurrentSkipListSet
    }
    
    
    public static SetType parseType(Class<?> cls) {
    	if(LinkedHashSet.class.equals(cls)) {
    		return SetType.LinkedHashSet;
    	}else if(TreeSet.class.equals(cls)) {
    		return SetType.TreeSet;
    	}else if(ConcurrentSkipListSet.class.equals(cls)) {
    		return SetType.ConcurrentSkipListSet;
    	}else {
    		return SetType.HashSet;
    	}
    }
    
    public static <T> Set<T> getMapNewInstance(SetType type) {
    	Set<T> result=null;
    	switch (type) {
		case LinkedHashSet:
			result=CollectionUtils.newLinkedHashSet();
			break;
		case TreeSet:
			result=CollectionUtils.newTreeSet();
			break;
		case ConcurrentSkipListSet:
			result=CollectionUtils.newConcurrentSet();
			break;
		default:
			result=CollectionUtils.newHashSet();
			break;
		}
		return result;
    }
    
    
    public static <T> Set<T> newInstance(Class<?> cls) {
    	return getMapNewInstance(parseType(cls));
    }
	
    @SafeVarargs
	public static <T> Set<T> of(T... objs){
    	Set<T> result=null;
    	if(objs!=null && objs.length>0) {
    		result=CollectionUtils.newHashSet();
    		for (int i = 0; i < objs.length; i++) {
    			result.add(objs[i]);
			}
    	}
		return result;
    }
    
    public static <T> Set<T> ofArray(T[] objs){
    	Set<T> result=null;
    	if(objs!=null && objs.length>0) {
    		result=CollectionUtils.newHashSet();
    		for (int i = 0; i < objs.length; i++) {
    			result.add(objs[i]);
    		}
    	}
    	return result;
    }
    
    public static <T> Set<T> ofCollection(Collection<T> objs){
    	Set<T> result=null;
    	if(objs!=null) {
    		result=getMapNewInstance(SetType.HashSet);
    		Iterator<T> it=objs.iterator();
        	while (it.hasNext()) {
        		result.add(it.next());
    		}
    	}
    	return result;
    }
    
	public static <T, V, R> Set<V> ofCollection(Collection<T> collections,TFunction<V, R> fn) {
		Set<V> set = CollectionUtils.newHashSet();
		Field field = LambdaUtils.getField(fn);
		for (T t : collections) {
			V v = BeanUtils.getFieldValue(field, t);
			set.add(v);
		}
		return set;
    }
    
    public static <T>T getFirst(Set<T> sets){
		if(CollectionUtils.isNotEmpty(sets)) {
			for (T t : sets) {
				if(t!= null) {
	                return t;
	            }
			}
		}
		return null;
    }

}
