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

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

import javax.servlet.http.HttpServletRequest;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * 字符串参数到对象的转换；
 *
 * @author xkliu
 */
public abstract class AbstractParameterEditor implements IEditor {
    private static final IEditorValue paramValue = (paramName, params, body, request) -> params.get(paramName);
    private static final IEditorValue headerValue = (paramName, params, body, request) -> request.getHeader(paramName);
    private static final IEditorValue bodyValue = (paramName, params, body, request) -> {
        if (body == null) {
            if (paramName != null) {
                return params.get(paramName);
            }
        } else {
            SwMap map = (SwMap) request.getAttribute(BODY_MAP);
            if (map != null) {
                return map.get(paramName);
            }

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

        return null;
    };

    private final IEditorValue editorValue;

//	AbstractParameterEditor() {
//		editorValue = paramValue;
//	}

    AbstractParameterEditor(int paramEditorType) {
        switch (paramEditorType) {
            case ParamEditor.TYPE_HEADER:
                editorValue = headerValue;
                break;
            case ParamEditor.TYPE_PARAM:
                editorValue = paramValue;
                break;
            case ParamEditor.TYPE_BODY:
                editorValue = bodyValue;
                break;
            default:
                throw new UnsupportedOperationException("not implement type: " + paramEditorType);
        }
    }

    protected static Date parseDateTime(String text) throws ParseException {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        df.setLenient(false);

        return df.parse(text);
    }

    protected static Date parseShortDateTime(String text) throws ParseException {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        df.setLenient(false);

        return df.parse(text);
    }

    protected static Date parseDate(String text) throws ParseException {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        df.setLenient(false);

        return df.parse(text);
    }

    @Override
    public Object getParamValue(String paramName, Class<?> paramType, IBeanContext context, Map<String, Object> params, String body, HttpServletRequest request) {
        if (StringUtils.isBlank(paramName)) {
            return null;
        }

        return parseText(editorValue.getValue(paramName, params, body, request));
    }

    protected abstract Object parseText(Object text);
}

interface IEditorValue {
    /**
     * 获取参数值
     *
     * @param paramName 参数名
     * @param params    HTTP请求参数集合
     * @param request   HTTP请求对象
     * @return 参数值
     */
    Object getValue(String paramName, Map<String, Object> params, String body, HttpServletRequest request);
}
