package cn.ibizlab.codegen.model;

import net.ibizsys.model.dataentity.IPSDataEntity;
import net.ibizsys.model.dataentity.logic.IPSDELogic;
import net.ibizsys.model.dataentity.logic.IPSDELogicLink;
import net.ibizsys.model.dataentity.logic.IPSDELogicNode;
import net.ibizsys.model.dataentity.logic.IPSDELogicParam;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class LogicModel extends BaseModel {

    private EntityModel entity;

    private boolean hasStartWF = false;
    private List<String> ruleGlobalParams = new ArrayList<>();

    private List<String> bpmnTnsParams = new ArrayList<>();

    private List<LogicNodeModel> logicNodeModels = new ArrayList<>();

    private List<LogicLinkModel> logicLinkModels = new ArrayList();

    public LogicModel(EntityModel entityModel, IPSDELogic iPSDELogic) {
        this.opt = iPSDELogic;
        this.entity = entityModel;
        this.setCodeName(iPSDELogic.getCodeName());
        this.setName(iPSDELogic.getName());
        this.setId(String.format("%1$s-%2$s", entity.getCodeName(), iPSDELogic.getCodeName()));
        if (!CollectionUtils.isEmpty(iPSDELogic.getPSDELogicParams())) {
            for (IPSDELogicParam iPSDELogicParam : iPSDELogic.getPSDELogicParams()) {
                String strParamName = iPSDELogicParam.getCodeName().toLowerCase();
                if (iPSDELogicParam.getParamPSDataEntity() != null) {
                    String strDataType = String.format("%s.core.%s.domain.%s",
                            entityModel.getSystem().getPackageName(),
                            iPSDELogicParam.getParamPSDataEntity().getPSSystemModule().getCodeName().toLowerCase(),
                            iPSDELogicParam.getParamPSDataEntity().getCodeName()
                    );
                    ruleGlobalParams.add(String.format("global %s %s;", strDataType, "param_" + strParamName));
                    String bpmnGlobalIdentifier = String.format("<tns:global identifier=\"%s\" type=\"%s.core.%s.domain.%s\" />",
                            strParamName,
                            entityModel.getSystem().getPackageName(),
                            iPSDELogicParam.getParamPSDataEntity().getPSSystemModule().getCodeName().toLowerCase(),
                            iPSDELogicParam.getParamPSDataEntity().getCodeName());
                    bpmnTnsParams.add(bpmnGlobalIdentifier);
                } else {
                    String strDataType = "java.util.Map";
                    ruleGlobalParams.add(String.format("global %s %s;", strDataType, "param_" + strParamName));
                }
            }
        }
        if (!CollectionUtils.isEmpty(iPSDELogic.getPSDELogicNodes())) {
            Map<String, String> map = new HashMap<>();
            for (IPSDELogicNode iPSDELogicNode : iPSDELogic.getPSDELogicNodes()) {
                LogicNodeModel logicNodeModel = new LogicNodeModel(this, iPSDELogicNode);
                logicNodeModels.add(logicNodeModel);
                if (!CollectionUtils.isEmpty(iPSDELogicNode.getPSDELogicLinks())) {
                    for (IPSDELogicLink iPSDELogicLink : iPSDELogicNode.getPSDELogicLinks()) {
                        logicLinkModels.add(new LogicLinkModel(this, iPSDELogicLink));
                    }
                }

                if (iPSDELogicNode.getLogicNodeType().equals("STARTWF")) {
                    hasStartWF = true;
                }
                try {
                    Method method = iPSDELogicNode.getClass().getDeclaredMethod("getDstPSDataEntity");
                    IPSDataEntity dstPSDataEntity = (IPSDataEntity) method.invoke(iPSDELogicNode);
                    if (!map.containsKey(dstPSDataEntity.getName())) {
                        String strDataType = String.format("%s.core.%s.service.%sService",
                                entityModel.getSystem().getPackageName(),
                                dstPSDataEntity.getPSSystemModule().getCodeName().toLowerCase(),
                                dstPSDataEntity.getCodeName()
                        );
                        ruleGlobalParams.add(String.format("global %s %s;", strDataType, String.format("%sservice", dstPSDataEntity.getCodeName().toLowerCase())));
                        map.put(dstPSDataEntity.getName(), dstPSDataEntity.getName());

                        String bpmnService = String.format("<tns:metaData express=\"T(cn.ibizlab.util.security.SpringContextHolder).getBean(T(%s.core.%s.service.%sService))\" name=\"%sservice\" type=\"service\"/>",
                                entityModel.getSystem().getPackageName(),
                                dstPSDataEntity.getPSSystemModule().getCodeName().toLowerCase(),
                                dstPSDataEntity.getCodeName(),
                                dstPSDataEntity.getCodeName().toLowerCase()
                        );
                        bpmnTnsParams.add(bpmnService);
                    }
                } catch (Exception e) {

                }
            }
        }

        if (hasStartWF) {
            String strDataType = "cn.ibizlab.util.client";
            ruleGlobalParams.add(String.format("global %s %s;", strDataType, "wfClient"));
        }
        if (true) {
            String strDataType = String.format("%s.core.%s.service.%sService",
                    entityModel.getSystem().getPackageName(),
                    entityModel.getDataEntity().getPSSystemModule().getCodeName().toLowerCase(),
                    entityModel.getDataEntity().getCodeName()
            );
            ruleGlobalParams.add(String.format("global %s %s;", strDataType, String.format("iBzSys%sDefaultService", entityModel.getCodeName())));


            String strBpmnService = String.format("<tns:metaData express=\"T(cn.ibizlab.util.security.SpringContextHolder).getBean(T(%s.core.%s.service.%sService))\" name=\"iBzSys%sDefaultService\" type=\"service\"/>",
                    entityModel.getSystem().getPackageName(),
                    entityModel.getDataEntity().getPSSystemModule().getCodeName().toLowerCase(),
                    entityModel.getDataEntity().getCodeName(),
                    entityModel.getDataEntity().getCodeName());
            bpmnTnsParams.add(strBpmnService);
        }
        ruleGlobalParams.add(String.format("global %s %s;", "cn.ibizlab.util.security.AuthenticationUser", "curuser"));
        bpmnTnsParams.add("<tns:metaData express=\"T(cn.ibizlab.util.security.AuthenticationUser).getAuthenticationUser()\" name=\"curuser\" type=\"session\"/>");
    }

    public IPSDELogic getPSDELogic() {
        return (IPSDELogic) opt;
    }

    public boolean isEnableBackend(){
        return this.getPSDELogic().isEnableBackend();
    }

    public EntityModel getEntity() {
        return entity;
    }

    public List<String> getRuleGlobalParams() {
        return ruleGlobalParams;
    }

    public List<String> getBpmnTnsParams() {
        return bpmnTnsParams;
    }

    public List<LogicNodeModel> getLogicNodeModels() {
        return logicNodeModels;
    }

    public List<LogicLinkModel> getLogicLinkModels() {
        return logicLinkModels;
    }
}
