package com.huigou.explorer.converters.mxgraph;

import com.alibaba.fastjson.JSON;
import com.mxgraph.model.mxCell;
import com.mxgraph.view.mxGraph;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author yonghuan
 */
public class MxTaskConverter extends AbstractMxVertexConverter implements MxElementConverter {

    private final static String VERTEX_STYLE_PATTERN = "html=1;whiteSpace=wrap;rounded=1;strokeColor=#bbbbbb;fillColor=#f9f9f9;shape=workflow.activities.%s";

    @Override
    public boolean supports(BaseElement baseElement) {
        return baseElement instanceof Task;
    }

    @Override
    protected void convertInternal(BpmnModel bpmnModel, Process process, mxGraph graph, FlowElement fe, mxCell vertex) {
        Task task = (Task) fe;
        String shapeName = camelCaseToUnderscoreCase(task.getClass().getSimpleName());
        vertex.setStyle(String.format(VERTEX_STYLE_PATTERN, shapeName));

        // 针对特定的Task设置专有的属性
        if (task instanceof UserTask) {
            UserTask userTask = (UserTask) task;
            parseUserTaskListeners(userTask, vertex);
            vertex.setAttribute("formKey", userTask.getFormKey());
            vertex.setAttribute("assignee", userTask.getAssignee());
            vertex.setAttribute("skipExpression", userTask.getSkipExpression());
            vertex.setAttribute("category", userTask.getCategory());
            vertex.setAttribute("dueDate", userTask.getDueDate());
            List<String> candidateUsers = userTask.getCandidateUsers();
            if (candidateUsers != null && candidateUsers.size() > 0) {
                vertex.setAttribute("candidateUsers", String.join(",", candidateUsers));
            }
            List<String> candidateGroups = userTask.getCandidateGroups();
            if (candidateGroups != null && candidateGroups.size() > 0) {
                vertex.setAttribute("candidateGroups", String.join(",", candidateGroups));
            }
        } else if (task instanceof ScriptTask) {
            ScriptTask scriptTask = (ScriptTask) task;
            vertex.setAttribute("resultVariable", scriptTask.getResultVariable());
            vertex.setAttribute("scriptFormat", scriptTask.getScriptFormat());
            vertex.setAttribute("script", scriptTask.getScript());
        } else if (task instanceof BusinessRuleTask) {
            BusinessRuleTask businessRuleTask = (BusinessRuleTask) task;
            vertex.setAttribute("inputVariables", String.join(",", businessRuleTask.getInputVariables()));
            vertex.setAttribute("resultVariableName", businessRuleTask.getResultVariableName());
            vertex.setAttribute("ruleNames", String.join(",", businessRuleTask.getRuleNames()));
            vertex.setAttribute("exclude", String.valueOf(businessRuleTask.isExclude()));
        } else if (task instanceof ServiceTask) {
            ServiceTask serviceTask = (ServiceTask) task;
            if ("class".equals(serviceTask.getImplementationType())) {
                vertex.setAttribute("javaClass", serviceTask.getImplementation());
            } else {
                vertex.setAttribute(serviceTask.getImplementationType(), serviceTask.getImplementation());
            }
            vertex.setAttribute("resultVariableName", serviceTask.getResultVariableName());
        } else if (task instanceof ReceiveTask) {

        }
    }

    /**
     * 解析用户任务事件监听器。
     */
    private void parseUserTaskListeners(UserTask userTask, mxCell cell) {
        List<Map<String, Object>> listeners = userTask.getTaskListeners().stream().map(activitiListener -> {
            Map<String, Object> listener = new HashMap<>(3);
            listener.put("event", activitiListener.getEvent());
            listener.put("implementationType", activitiListener.getImplementationType());
            listener.put("implementation", activitiListener.getImplementation());
            listener.put("fieldExtensions", activitiListener.getFieldExtensions());
            return listener;
        }).collect(Collectors.toList());
        if (listeners.size() > 0) {
            cell.setAttribute("taskListeners", JSON.toJSONString(listeners));
        }
    }
}
