package cc.smtweb.framework.core.mvc.controller.binder.body;

import cc.smtweb.framework.core.common.SwMap;
import cc.smtweb.framework.core.exception.BindBeanException;
import cc.smtweb.framework.core.mvc.controller.IBeanContext;
import cc.smtweb.framework.core.mvc.controller.IEditor;
import cc.smtweb.framework.core.util.JsonUtil;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * API函数@SwBody参数的转换处理，POST请求直接转换Json内容为Bean对象，GET请求转换Map请求参数为Bean对
 *
 * @author xkliu
 */
public class BeanBodyEditor implements IEditor {
    @Override
    public Object getParamValue(String paramName, Class<?> paramType, IBeanContext context, Map<String, Object> params, String body, HttpServletRequest request) {
        if (paramName != null) {
            Object map = request.getAttribute(BODY_MAP);
            if (map != null) {
                return getFieldValue((SwMap) map, paramName, paramType);
            }
        }

        if (body != null) {
            return getPostValue(paramName, paramType, body, request);
        } else {
            return getGetValue(paramName, paramType, params);
        }
    }

    private Object getGetValue(String paramName, Class<?> paramType, Map<String, Object> params) {
        if (paramName == null) {
            return JsonUtil.parseSimple(params, paramType);
        }

        // Json字符进行类型转化
        Object result = params.get(paramName);
        if (result == null) {
            return null;
        }

        if (paramType.isAssignableFrom(result.getClass())) {
            return result;
        }

        throw new BindBeanException("传入的 @SwBody(" + paramName + ") " + paramType.getName() + "类型不一致! " + result.getClass().getName());
    }

    private Object getPostValue(String paramName, Class<?> paramType, String body, HttpServletRequest request) {
        if (body == null || StringUtils.isBlank(body)) {
            return null;
        }

        if (paramName == null) {
            return JsonUtil.parse(body, paramType);
        } else {
            SwMap map = JsonUtil.parse(body, SwMap.class);
            if (map != null) {
                request.setAttribute(BODY_MAP, map);
                return getFieldValue(map, paramName, paramType);
            }

            return null;
        }
    }

    private Object getFieldValue(SwMap result, String paramName, Class<?> paramType) {
        Object value = result.get(paramName);
        if (value == null) {
            return null;
        }

        if (value instanceof Map) {
            return BeanUtil.toBean((Map) value, paramType);
        }

        throw new BindBeanException("传入的 @SwBody(" + paramName + ") 值非Object类型! " + value.getClass().getName());
    }
}
