package cn.reghao.oss.console.template.attribute;

import cn.reghao.oss.console.account.model.constant.MenuType;
import cn.reghao.oss.console.account.model.constant.RoleType;
import cn.reghao.oss.console.account.service.UserContext;
import cn.reghao.oss.console.app.model.constant.AppType;
import cn.reghao.oss.console.util.EnvType;
import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.context.ITemplateContext;
import org.thymeleaf.engine.AttributeName;
import org.thymeleaf.model.IProcessableElementTag;
import org.thymeleaf.postprocessor.IPostProcessor;
import org.thymeleaf.processor.element.AbstractAttributeTagProcessor;
import org.thymeleaf.processor.element.IElementTagStructureHandler;
import org.thymeleaf.standard.expression.*;
import org.thymeleaf.templatemode.TemplateMode;

import java.util.*;

/**
 * 根据字典标识生成下拉列表
 * @author 小懒虫
 * @date 2018/8/14
 */
public class SelectDictAttrProcessor extends AbstractAttributeTagProcessor {
    private final static Map<String, Map<String, Map<String, Object>>> selectCache = new HashMap<>();
    private final static Map<String, Map<String, Object>> localCache = new HashMap<>();
    static {
        // 只会在应用启动时初始化一次
        localCache.put("MENU_STATUS", new HashMap<>());
        localCache.get("MENU_STATUS").put("ENABLE", true);
        localCache.get("MENU_STATUS").put("DISABLE", false);

        localCache.put("MENU_TYPE", new HashMap<>());
        for (MenuType menuType : MenuType.values()) {
            localCache.get("MENU_TYPE").put(menuType.name(), menuType.name());
        }

        localCache.put("LOGLEVEL", new HashMap<>());
        localCache.get("LOGLEVEL").put("info", "info");
        localCache.get("LOGLEVEL").put("error", "error");

        selectCache.put("ENVIRONMENT", new HashMap<>());
        selectCache.put("APP_TYPE", new HashMap<>());
    }
    
    public static final int PRECEDENCE = 1400;
    public static final String ATTR_NAME = "dict";
    public static final String SELECTED_ATTR_NAME= "mo-selected";
    public static final String EMPTY_ATTR_NAME= "mo-empty";

    public SelectDictAttrProcessor(final TemplateMode templateMode, final String dialectPrefix) {
        super(templateMode, dialectPrefix, null, false, ATTR_NAME, true, PRECEDENCE, true);
    }

    public SelectDictAttrProcessor(final TemplateMode templateMode, final String dialectPrefix, String attrName, int precedence) {
        super(templateMode, dialectPrefix, null, false, attrName, true, precedence, true);
    }

    /**
     * 获取 select 标签下的 options
     *
     * @param
     * @return
     * @date 2023-12-01 15:15:50
     */
    private Map<String, Object> getSelectOptions(String attr) {
        if ("ENVIRONMENT".equals(attr) || "APP_TYPE".equals(attr)) {
            Map<String, Map<String, Object>> map = selectCache.get(attr);
            if (map.isEmpty()) {
                if ("ENVIRONMENT".equals(attr)) {
                    for (RoleType roleType : RoleType.values()) {
                        String role = roleType.name();
                        if (role.equals(RoleType.ROLE_ADMIN.name())) {
                            Map<String, Object> map1 = new HashMap<>();
                            for (EnvType envType : EnvType.values()) {
                                map1.put(envType.name(), envType.name());
                            }
                            map.put(role, map1);
                        } else if (role.equals(RoleType.ROLE_BACKEND.name()) || role.equals(RoleType.ROLE_FRONTEND.name())) {
                            Map<String, Object> map1 = new HashMap<>();
                            map1.put(EnvType.uat.name(), EnvType.uat.name());
                            map1.put(EnvType.test.name(), EnvType.test.name());
                            map.put(role, map1);
                        } else {
                            Map<String, Object> map1 = new HashMap<>();
                            map1.put(EnvType.test.name(), EnvType.test.name());
                            map.put(role, map1);
                        }
                    }
                } else {
                    for (RoleType roleType : RoleType.values()) {
                        String role = roleType.name();
                        if (role.equals(RoleType.ROLE_ADMIN.name())) {
                            Map<String, Object> map1 = new HashMap<>();
                            for (AppType appType : AppType.values()) {
                                map1.put(appType.name(), appType.name());
                            }
                            map.put(role, map1);
                        } else if (role.equals(RoleType.ROLE_BACKEND.name())) {
                            Map<String, Object> map1 = new HashMap<>();
                            map1.put(AppType.dotnetCore.name(), AppType.dotnetCore.getName());
                            map.put(role, map1);
                        } else if (role.equals(RoleType.ROLE_FRONTEND.name())) {
                            Map<String, Object> map1 = new HashMap<>();
                            map1.put(AppType.npm.name(), AppType.npm.getName());
                            map.put(role, map1);
                        } else {
                            Map<String, Object> map1 = new HashMap<>();
                            map1.put(AppType.maven.name(), AppType.maven.getName());
                            map.put(role, map1);
                        }
                    }
                }
            }

            String role = UserContext.getUserRole();
            return map.get(role);
        } else {
            return localCache.get(attr);
        }
    }

    @Override
    protected void doProcess(
            final ITemplateContext context,
            final IProcessableElementTag tag,
            final AttributeName attributeName,
            final String attributeValue,
            final IElementTagStructureHandler structureHandler) {

        // 如果属性值为空或者标签不为select，则不处理
        String elementName = tag.getElementCompleteName();
        if(attributeValue.isEmpty() || !"select".equals(elementName)) {
            return;
        }

        // 获取列表对象，空则不处理
        //Map<String, Object> valueList = localCache.get(attributeValue);
        Map<String, Object> valueList = getSelectOptions(attributeValue);
        if(!valueList.isEmpty()) {
            doProcess(context, tag, structureHandler, valueList);
        }
    }

    protected void doProcess(
            final ITemplateContext context,
            final IProcessableElementTag tag,
            final IElementTagStructureHandler structureHandler,
            Map<String, Object> valueList) {

        // 获取默认选中值
        String attributeSelectedValue = tag.getAttributeValue(SELECTED_ATTR_NAME);
        Object selectedValue = null;
        final IEngineConfiguration configuration = context.getConfiguration();
        if (attributeSelectedValue != null && !attributeSelectedValue.isEmpty()){
            final IStandardExpressionParser expressionParser = StandardExpressions.getExpressionParser(configuration);
            final IStandardExpression expression = expressionParser.parseExpression(context, attributeSelectedValue);
            final Object expressionResult;
            if (expression instanceof FragmentExpression) {
                final FragmentExpression.ExecutedFragmentExpression executedFragmentExpression =
                        FragmentExpression.createExecutedFragmentExpression(context, (FragmentExpression) expression);
                expressionResult =
                        FragmentExpression.resolveExecutedFragmentExpression(context, executedFragmentExpression, true);
            } else {
                expressionResult = expression.execute(context, StandardExpressionExecutionContext.NORMAL);
            }
            if (expressionResult == NoOpToken.VALUE) {
                return;
            }
            selectedValue = (expressionResult == null ? "" : expressionResult);
        }

        // 拼装下拉列表选项
        List<String> keyList = new ArrayList<>();
        if (selectedValue instanceof List){
            ((List) selectedValue).forEach(item -> keyList.add(String.valueOf(item)));
        }else {
            keyList.add(selectedValue == null ? "" : selectedValue.toString());
        }
        StringBuilder optionContent = new StringBuilder();
        valueList.forEach((key, val) -> {
            optionContent.append("<option value = '").append(key);
            if (keyList.contains(String.valueOf(val))){
                optionContent.append("' ").append("selected='selected");
            }
            optionContent.append("'>").append(val).append("</option>");
        });

        // 判断是添加空值选项
        String attributeEmptyValue = tag.getAttributeValue(EMPTY_ATTR_NAME);
        if(attributeEmptyValue != null){
            String emptyStr = "<option value=''>" + attributeEmptyValue + "</option>";
            optionContent.insert(0, emptyStr);
        }

        // 返回新的HTML节点
        final Set<IPostProcessor> postProcessors = configuration.getPostProcessors(getTemplateMode());
        if (postProcessors.isEmpty()) {
            structureHandler.removeAttribute(SELECTED_ATTR_NAME);
            structureHandler.removeAttribute(EMPTY_ATTR_NAME);
            structureHandler.setBody(optionContent, false);
        }
    }

    @Override
    public int hashCode() {
        return super.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }
}
