package com.tykj.workflowcore.workflow_editer.listener;

import com.tykj.workflowcore.api.controller.ApiController;
import com.tykj.workflowcore.api.entity.InvokeRequest;
import com.tykj.workflowcore.api.entity.Parameter;
import com.tykj.workflowcore.base.result.ApiException;
import com.tykj.workflowcore.workflow_editer.entity.enums.JavaTypeEnum;
import com.tykj.workflowcore.workflow_editer.entity.VariableStorage;
import com.tykj.workflowcore.workflow_editer.entity.vo.ParameterVo;
import com.tykj.workflowcore.workflow_editer.entity.vo.SearchVariableStorageVo;
import com.tykj.workflowcore.workflow_editer.service.DataHistoryService;
import com.tykj.workflowcore.workflow_editer.service.VariableStorageService;
import org.flowable.bpmn.model.EndEvent;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.api.delegate.Expression;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.engine.*;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
import org.flowable.engine.delegate.event.FlowableActivityEvent;
import org.flowable.engine.delegate.event.impl.FlowableActivityEventImpl;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;


import java.util.*;

/**
 * @author HuangXiahao
 * @version V1.0
 * @class ProcessEndListener
 * @packageName com.tykj.workflowcore.workflow_editer.listener
 **/
@Component
public class ProcessEndListener extends AbstractFlowableEngineEventListener {

    @Autowired
    RuntimeService runtimeService;

    @Autowired
    RepositoryService repositoryService;

    @Autowired
    FormService formService;

    @Autowired
    VariableStorageService variableStorageService;

    @Autowired
    ProcessEngineConfigurationImpl processEngineConfiguration;

    @Autowired
    ApiController apiController;

    @Autowired
    TaskService taskService;

    @Autowired
    DataHistoryService dataHistoryService;

    @Override
    protected void processCompleted(FlowableEngineEntityEvent event) {
    }

    @Override
    protected void taskCompleted(FlowableEngineEntityEvent event) {
        super.taskCompleted(event);
    }

    @Override
    public void onEvent(FlowableEvent flowableEvent) {
        super.onEvent(flowableEvent);
    }

    @Override
    protected void activityCompleted(FlowableActivityEvent event) {
        super.activityCompleted(event);
        if (event instanceof FlowableActivityEventImpl){
            DelegateExecution execution = ((FlowableActivityEventImpl) event).getExecution();
            if (execution.getCurrentFlowElement() instanceof EndEvent || execution.getCurrentFlowElement() instanceof UserTask){
                System.out.println("流程结束了");
                //拿到流程定义ID
                String processDefinitionId = execution.getProcessDefinitionId();
                //通过定义Id取到flowKey
                String flowKey = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).list().get(0).getKey();
                List<VariableStorage> variableStorageList = variableStorageService.searchVariableStorageList(new SearchVariableStorageVo(flowKey,execution.getCurrentActivityId()));
                for (VariableStorage variableStorage : variableStorageList) {
                    List<ParameterVo> parameterVoList = variableStorage.getParams();
                    InvokeRequest invokeRequest = new InvokeRequest();
                    invokeRequest.setClassName(variableStorage.getClassName());
                    invokeRequest.setName(variableStorage.getName());
                    invokeRequest.setParams(getApiInvokeParam(parameterVoList,execution));
                    //调用服务接口
                    apiController.invoke(invokeRequest);
                }
            }
//                //开始节点
//            if (execution.getCurrentFlowElement() instanceof StartEvent){
//                DataHistory dataHistory = new DataHistory();
//                StartEvent startEvent = (StartEvent) execution.getCurrentFlowElement();
//                //流程id  实例id  pageId  datas userId
//                String processInstanceBusinessKey = execution.getProcessInstanceBusinessKey();
//                dataHistory.setFlowKey(processInstanceBusinessKey);
//                dataHistory.setProcessInstanceId(execution.getProcessInstanceId());
//                dataHistory.setPageId(startEvent.getFormKey());
////                dataHistory.setUserId();
////                dataHistory.setDatas();
//                System.out.println(processInstanceBusinessKey);
//
//                String formKey = startEvent.getFormKey();
//                //通过formKey查询出页面
//
//            }
//            if (execution.getCurrentFlowElement() instanceof UserTask){
//                //查询任务
//                Task task = taskService.createTaskQuery().singleResult();
//                Map<String, Object> variables = taskService.getVariables(task.getId());
//                DataHistory dataHistory = new DataHistory();
//                String datas = JSON.toJSONString(variables);
//                //流程实例id
//                String processInstanceId = task.getProcessInstanceId();
//                //当前节点id
//                String processInstanceBusinessKey = execution.getProcessInstanceBusinessKey();
//
////              dataHistory.setTaskId(taskId);
//                dataHistory.setDatas(datas);
//                dataHistory.setProcessInstanceId(processInstanceId);
//                dataHistoryService.saveData(dataHistory);
//            }
        }
    }

    /**
     * 获取调用Api用的参数
     *
     * @param parameterVoList 调用服务接口vo
     * @return 调用服务接口实体
     */
    public List<Parameter> getApiInvokeParam(List<ParameterVo> parameterVoList,DelegateExecution execution) {
        //拿出taskId
        List<Parameter> parameterList = new ArrayList<>();
        for (int i = 0; i < parameterVoList.size(); i++) {
            ParameterVo parameterVo = parameterVoList.get(i);
            Parameter parameter = new Parameter();
            parameter.setClassName(parameterVo.getClassName());
            Map<String, Object> instance = new HashMap<>();
            FillParameter(instance,parameterVoList.get(i),execution);
            parameter.setInstance(instance.get(parameterVo.getName()));
            parameterList.add(parameter);
        }
        return parameterList;
    }

    public Map<String, Object> FillParameter(Map<String, Object> instance,ParameterVo parameterVo,DelegateExecution execution)  {
        if (!StringUtils.isEmpty(parameterVo.getExp())) {
            //如果是表示式  如：${people}
            instance.put(parameterVo.getName(),getProcessValue(execution, parameterVo.getExp()));
        }else {
            if (instance.get(parameterVo.getName())==null){
                //判断基础类型 为基础类型
                Class<?> aClass = null;
                try {
                    aClass = Class.forName(parameterVo.getClassName());
                }catch (ClassNotFoundException e){
                    throw new ApiException("填充参数时类型转换失败，className:"+parameterVo.getClassName());
                }
                if (checkIn(parameterVo.getClassName())){
                    instance.put(parameterVo.getName(),null);
                }else
                if (Collection.class.isAssignableFrom(aClass)){
                    if (List.class.isAssignableFrom(aClass)){
                        instance.put(parameterVo.getName(),new ArrayList<>());
                    }else {
                        instance.put(parameterVo.getName(),new HashSet<>());
                    }
                }else {
                    instance.put(parameterVo.getName(),new HashMap<>());
                }
            }
        }
        List<ParameterVo> parameterVoList = parameterVo.getFields();
        if (parameterVoList!=null&&parameterVoList.size()>0){
            for (int i = 0; i < parameterVoList.size() ; i++) {
                if (instance.get(parameterVo.getName()) instanceof Map){
                    FillParameter((Map<String, Object>) instance.get(parameterVo.getName()),parameterVoList.get(i),execution);
                }
            }
        }
        return instance;
    }

    public Object getProcessValue(DelegateExecution execution, String exp) {
        // processInstance -> ExecutionEntity
        Expression expression = processEngineConfiguration.getExpressionManager().createExpression(exp);
        return expression.getValue(execution);
    }

    public Boolean checkIn(String className){
        JavaTypeEnum[] values = JavaTypeEnum.values();
        for (int i = 0; i < values.length ; i++) {
            if (className.equals(values[i].getName())){
                return true;
            };
        }
        return false;
    }


}
