package com.brframework.commoncms.core.layout.layout;

import com.brframework.commonweb.exception.HandleException;
import com.brframework.commonweb.json.JSONResult;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.brframework.commoncms.annatotion.layout.EditLayout;
import com.brframework.commoncms.core.layout.AbstractPanelLayout;
import com.brframework.commoncms.core.layout.PanelLayoutColumn;
import com.brframework.commoncms.utils.ControllerUtil;
import lombok.Data;
import org.springframework.core.annotation.AnnotatedElementUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * @author xu
 * @date 2018/9/26 13:49
 */
@Data
public class PanelEditLayout extends AbstractPanelLayout {

    /**
     * 数据编辑
     */
    public static final String TYPE = "EDIT";


    private List<PanelLayoutColumn> columns;

    /**
     * 数据填充的URL
     * 默认情况下是submitUrl的GET请求
     */
    private String paddingUrl;

    /**
     * 数据提交地址
     */
    private String submitUrl;
    /**
     * 数据提交方法
     */
    private String submitMethod;

    @Override
    public String getType() {
        return TYPE;
    }

    @Override
    public void create(Method method) throws Throwable {
        init(method);

        Class<?> returnType = method.getReturnType();

        if (!returnType.getName().equals(JSONResult.class.getName())) {
            throw new HandleException("返回值类型" + returnType.getName() + "非协议类型");
        }

        //通过解析方法参数生成接口调用需要的数据
        List<Class> apiTypes = ControllerUtil.getParamApiModelClass(method);
        columns = Lists.newArrayList();
        for (Class apiType : apiTypes) {
            List<Field> declaredFields = ControllerUtil.handlerPropertyField(
                    ControllerUtil.getAllField(apiType)
            );
            for (Field declaredField : declaredFields) {
                columns.add(ControllerUtil.createColumn(declaredField));
            }
        }

        //加载uri里的参数，对提交和Padding的url进行填充
        Map<String, String> uriParameter = ControllerUtil.getUriParameter(method);
        submitUrl = ControllerUtil.getControllerUrl(method);
        paddingUrl = getPaddingUrl(method);
        if(Strings.isNullOrEmpty(paddingUrl)){
            //处理方法名映射
            String paddingMappingMethod = getPaddingMappingMethod(method);
            if(!Strings.isNullOrEmpty(paddingMappingMethod)){
                paddingUrl = handlerPaddingMapping(method, paddingMappingMethod);
            }
        }

        for (String key : uriParameter.keySet()) {
            submitUrl = submitUrl.replace("{" + key + "}", uriParameter.get(key));
            paddingUrl = paddingUrl.replace("{" + key + "}", uriParameter.get(key));
        }

        submitMethod = ControllerUtil.getHttpMethod(method);



        //将URL内的参数加入到隐藏列里
//        Map<String, String> hideColumns = ControllerUtil.getUriParameter(method);
//        for (String key : hideColumns.keySet()) {
//            LayoutHideColumn hideColumn = new LayoutHideColumn();
//            hideColumn.setKey(key);
//            hideColumn.setValue(hideColumns.get(key));
//            columns.add(hideColumn);
//        }
    }

    private String handlerPaddingMapping(Method method, String paddingMappingMethod){
        if(Strings.isNullOrEmpty(paddingMappingMethod)) return null;

        Method[] declaredMethods = method.getDeclaringClass().getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            if (declaredMethod.getName().equals(paddingMappingMethod)) {
                return ControllerUtil.getControllerUrl(declaredMethod);
            }
        }

        return null;
    }

    /**
     * 数据填充
     * @param method
     * @return
     */
    protected String getPaddingUrl(Method method){
        EditLayout editLayout = AnnotatedElementUtils.findMergedAnnotation(method, EditLayout.class);

        return editLayout.paddingUrl();
    }

    /**
     * 数据填充映射方法
     * @param method
     * @return
     */
    protected String getPaddingMappingMethod(Method method){
        EditLayout editLayout = AnnotatedElementUtils.findMergedAnnotation(method, EditLayout.class);
        return editLayout.paddingMappingMethod();
    }

}
