package com.steerinfo.util;


import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class JsonObjectArgResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.hasParameterAnnotation(JsonOb.class);
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        HttpServletRequest servletRequest = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
        JsonNode jsonNode = getParameterJson(servletRequest);
        Type type = methodParameter.getGenericParameterType();
        if (type instanceof TypeVariable) {
            //当参数类型为泛型时，获取其真实类型
            type = methodParameter.getParameterType();
        }
        JavaType javaType = objectMapper.getTypeFactory().constructType(type);
        if (type.equals(Date.class)) {
            String eL = "[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}";
            Pattern p = Pattern.compile(eL);
            Matcher m = p.matcher(jsonNode.textValue());
            if (m.matches()) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                return sdf.parse(jsonNode.textValue());
            }
        }
        return objectMapper.readValue(jsonNode.toString(), javaType);
    }

    private JsonNode getParameterJson(HttpServletRequest request) throws Exception {
        JsonNode param = null;
        JsonNode jsonNode = (JsonNode) request.getAttribute("jsonNode");
        if (jsonNode == null) {
            InputStream in = request.getInputStream();
            ObjectMapper om = new ObjectMapper();
            try {
                jsonNode = om.readTree(in);
            } catch (Exception e) {
                throw new Exception("解析方法参数出错，请检查请求参数及参数格式是否合法（JSON格式）");
            }
            request.setAttribute("jsonNode", jsonNode);
        }
        Iterator<JsonNode> it = jsonNode.elements();
        if (it.hasNext()) {
            param = it.next();
            it.remove();
        }
        return param;
    }
}
