package com.github.wxiaoqi.security.common.util;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;  

public abstract class JsonUtil {  
  
    private static final ObjectMapper mapper = new ObjectMapper();  
	private static final Logger log = LoggerFactory.getLogger(JsonUtil.class);
	
	static {
		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		mapper.setSerializationInclusion(Include.NON_NULL);
	}
	
    public static String objectToJson(Object data) {  
        try {  
            return mapper.writeValueAsString(data);
        } catch (Exception e) {
        	log.error("JsonUtil.objectToJson execution failure!");
            throw new RuntimeException(e);
        }  
    }  
      
    public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {  
        try {
        	if (StringUtils.isEmpty(jsonData)) return null;
            return mapper.readValue(jsonData, beanType);  
        } catch (Exception e) {
        	log.error("JsonUtil.jsonToPojo execution failure!");
            throw new RuntimeException(e);
        }  
    }
    
    public static <T, R> R objectToObject(T srcObj, Class<R> beanType) {  
    	String toJson = objectToJson(srcObj);
    	return jsonToPojo(toJson, beanType);
    }
    
    @SuppressWarnings("rawtypes")
	public static <T, R> R objectToObjectByTypeReference(T srcObj, TypeReference valueTypeRef) {  
    	String toJson = objectToJson(srcObj);
    	return toPojoByTypeReference(toJson, valueTypeRef);
    }
    
	@SuppressWarnings("unchecked")
	public static <T, R> Map<T, R> jsonToMap(String json) {
        return jsonToPojo(json, Map.class);
    }
      
    public static <T> List<T> jsonToList(String jsonData, Class<T> beanType) {  
    	try {
    		if (StringUtils.isEmpty(jsonData)) return null;
    		JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, beanType);  
            return mapper.readValue(jsonData, javaType);  
        } catch (Exception e) {
        	log.error("JsonUtil.jsonToList execution failure!");
            throw new RuntimeException(e);  
        }  
    }
    
	@SuppressWarnings("rawtypes")
	public static <T> T toPojoByTypeReference(String jsonData, TypeReference valueTypeRef) {
		try {
			if (StringUtils.isEmpty(jsonData)) return null;
			return mapper.readValue(jsonData, valueTypeRef);
		} catch (Exception e) {
			log.error("JsonUtil.jsonToPojo execution failure!");
			throw new RuntimeException(e);
		}
	}
    
    
    public static <T> T jsonToGeneric(String jsonData, Class<T> beanType, Class<?> resultType) {  
        try {
        	if (StringUtils.isEmpty(jsonData)) return null;
        	JavaType javaType = mapper.getTypeFactory().constructParametricType(beanType, beanType);  
            return mapper.readValue(jsonData, javaType);  
        } catch (Exception e) {
        	log.error("JsonUtil.jsonToList execution failure!");
            throw new RuntimeException(e);  
        }  
    }
}