package com.lideeyunji.core.framework.config.aspect.enhance.criteria;


import com.lideeyunji.core.framework.config.aspect.enhance.model.EnhanceContext;
import com.lideeyunji.core.framework.config.aspect.enhance.model.JavaEnhanceEnum;
import com.lideeyunji.core.framework.config.aspect.enhance.plugin.AfterAdvicePlugin;
import com.lideeyunji.core.framework.config.aspect.enhance.plugin.PluginManager;
import com.lideeyunji.core.framework.entity.EnhanceJavaEntity;
import com.lideeyunji.core.framework.utils.Func;
import com.lideeyunji.tool.framework.yunji.tool.spring.SpringUtils;
import com.lideeyunji.tool.framework.yunji.utils.FuncBase;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class CriteriaFilterAdvicePluginUtils {

    //后置增强，列表的（串行，并集等）
    public static void executeAfterJavaEnhance(EnhanceContext context, List<EnhanceJavaEntity> javaEntityList) throws Exception {
        if (Func.isEmpty(javaEntityList) || javaEntityList.size() < 2) {
            return;
        }
        //只有后置增强才有集合操作
        List<EnhanceJavaEntity> afterJavaList = javaEntityList.stream().filter(javaEntity -> {
            Object o = null;
            if (Func.equals(JavaEnhanceEnum.SPRING.getType(), javaEntity.getJavaType())) {
                o = SpringUtils.getBean(javaEntity.getJavaClassUrl());
            } else if (Func.equals(JavaEnhanceEnum.CLASS.getType(), javaEntity.getJavaType())) {
                try {
                    o = Class.forName(javaEntity.getJavaClassUrl()).newInstance();
                } catch (InstantiationException | IllegalAccessException | ClassNotFoundException ignored) {}
            }
            return o instanceof AfterAdvicePlugin;
        }).collect(Collectors.toList());

        if (Func.isEmpty(afterJavaList) || afterJavaList.size() < 2) {
            if (Func.isNotEmpty(afterJavaList)) {
                javaEntityList.removeAll(afterJavaList);
            }
            return;
        }

        //根据序号排序
        afterJavaList.sort(
                Comparator.comparing(
                        EnhanceJavaEntity::getSort, Comparator.nullsLast(Integer::compareTo)));

        for (int i = 0; i < afterJavaList.size() - 1; i++) {
            EnhanceJavaEntity leftEntity = null;
            EnhanceJavaEntity rightEntity = null;
            if (i == 0) {
                leftEntity = afterJavaList.get(i);
                rightEntity = afterJavaList.get(i + 1);
            } else {
                rightEntity = afterJavaList.get(i + 1);
            }

            switch (rightEntity.getListResultHandleType()) {
                case "1":
                    //执行合集操作
                    executAfterByOr(leftEntity, rightEntity, context);
                    break;
                case "2":
                    //执行差集操作
                    executAfterByDiffer(leftEntity, rightEntity, context);
                    break;
                case "3":
                    //执行并集操作
                    executAfterByUnion(leftEntity, rightEntity, context);
                    break;
                case "4":
                    //执行交集操作
                    executAfterBySerction(leftEntity, rightEntity, context);
                    break;
                default:
                case "0":
                    //执行串行操作
                    executAfterByAnd(leftEntity, rightEntity, context);
                    break;
            }

        }

    }

    //串行
    private static void executAfterByAnd(EnhanceJavaEntity leftEntity, EnhanceJavaEntity rightEntity, EnhanceContext context) throws Exception {

        AfterAdvicePlugin leftPlugin = judgeLeftPlugin(leftEntity);
        AfterAdvicePlugin rightPlugin = (AfterAdvicePlugin) PluginManager.getPlugin(rightEntity);
        AndCriteriaFilterAdvicePlugin andAdvicePlugin = new AndCriteriaFilterAdvicePlugin(leftPlugin, rightPlugin);
        andAdvicePlugin.execute(context);

    }

    //合集
    private static void executAfterByOr(EnhanceJavaEntity leftEntity, EnhanceJavaEntity rightEntity, EnhanceContext context) throws Exception {
        AfterAdvicePlugin leftPlugin = judgeLeftPlugin(leftEntity);
        AfterAdvicePlugin rightPlugin = (AfterAdvicePlugin)PluginManager.getPlugin(rightEntity);
        OrCriteriaFilterAdvicePlugin orAdvicePlugin = new OrCriteriaFilterAdvicePlugin(leftPlugin, rightPlugin);
        orAdvicePlugin.execute(context);

    }

    //差集
    private static void executAfterByDiffer(EnhanceJavaEntity leftEntity, EnhanceJavaEntity rightEntity, EnhanceContext context) throws Exception {
        AfterAdvicePlugin leftPlugin = judgeLeftPlugin(leftEntity);
        AfterAdvicePlugin rightPlugin = (AfterAdvicePlugin)PluginManager.getPlugin(rightEntity);
        DifferenceCriteriaFilterAdvicePlugin differPlugin = new DifferenceCriteriaFilterAdvicePlugin(leftPlugin, rightPlugin);
        differPlugin.execute(context);
    }

    //并集
    private static void executAfterByUnion(EnhanceJavaEntity leftEntity, EnhanceJavaEntity rightEntity, EnhanceContext context) throws Exception {

        AfterAdvicePlugin leftPlugin = judgeLeftPlugin(leftEntity);
        AfterAdvicePlugin rightPlugin = (AfterAdvicePlugin)PluginManager.getPlugin(rightEntity);
        UnionCriteriaFilterAdvicePlugin unionPlugin = new UnionCriteriaFilterAdvicePlugin(leftPlugin, rightPlugin);
        unionPlugin.execute(context);


    }

    //交集
    private static void executAfterBySerction(EnhanceJavaEntity leftEntity, EnhanceJavaEntity rightEntity, EnhanceContext context) throws Exception {
        AfterAdvicePlugin leftPlugin = judgeLeftPlugin(leftEntity);
        AfterAdvicePlugin rightPlugin = (AfterAdvicePlugin)PluginManager.getPlugin(rightEntity);
        IntersectionCriteriaFilterAdvicePlugin intersectionPlugin = new IntersectionCriteriaFilterAdvicePlugin(leftPlugin, rightPlugin);
        intersectionPlugin.execute(context);

    }

    //判断左边是否为空
    private static AfterAdvicePlugin judgeLeftPlugin(EnhanceJavaEntity leftEntity) {
        AfterAdvicePlugin leftPlugin = null;
        if (FuncBase.isNotEmpty(leftEntity)) {
            leftPlugin = (AfterAdvicePlugin)PluginManager.getPlugin(leftEntity);
        } else {
            leftPlugin = enhanceContext -> {
            };
        }
        return leftPlugin;
    }
}
