package cn.ibizlab.r7.runtime.activiti.listener;

import cn.ibizlab.r7.runtime.activiti.service.external.UniWFService;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.FormProperty;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.delegate.event.ActivitiEvent;
import org.activiti.engine.delegate.event.ActivitiEventListener;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.delegate.event.impl.ActivitiActivityEventImpl;
import org.activiti.engine.delegate.event.impl.ActivitiEntityEventImpl;
import org.activiti.engine.delegate.event.impl.ActivitiEventImpl;
import org.activiti.engine.delegate.event.impl.ActivitiProcessStartedEventImpl;
import org.activiti.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.activiti.engine.impl.persistence.entity.TaskEntityImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.util.List;

/**
 * 流程实例监听器，监听流程实例启动、流转、结束状态
 * 1.流程状态发生变化时，将实例信息同步到统一工作流平台
 * 2.到达流程节点时，调用统一接口，查询当前节点办理人并设置到引擎中
 */
@Component
public class ProcessInstanceListener implements ActivitiEventListener {

    @Autowired
    RepositoryService repositoryService;
    @Autowired
    RuntimeService runtimeService;
    @Autowired
    UniWFService uniWFService;

    @Override
    public void onEvent(ActivitiEvent event) {

        ActivitiEventType eventType = event.getType();
        System.out.println("eventType:"+event.getType());
        //步骤开始
        if(eventType == ActivitiEventType.ACTIVITY_STARTED){

            System.out.println("步骤开始");
            UserTask userTask=getUserTask(event);
            if(ObjectUtils.isEmpty(userTask))
                return ;
            String processInstanceId=event.getProcessInstanceId();
            //获取步骤操作者对应的人员
            List<String> uniwfStepUsers=uniWFService.calculateCurrentWFStepActor(processInstanceId,userTask.getId());
            //设置步骤操作人员
            runtimeService.setVariable(processInstanceId,"candidateUsers",uniwfStepUsers);
            //回调
            uniWFService.callbackWFActivityStarted(event,userTask);

        }
        //步骤结束
        if(eventType == ActivitiEventType.ACTIVITY_COMPLETED){
            System.out.println("步骤结束");
            UserTask userTask=getUserTask(event);
            uniWFService.callbackWFActivityCompleted(event,userTask);
        }
        //步骤取消
        if(eventType == ActivitiEventType.ACTIVITY_CANCELLED){
            System.out.println("步骤取消");
            UserTask userTask=getUserTask(event);
        }
        //实例启动
        if(eventType == ActivitiEventType.PROCESS_STARTED){

            System.out.println("流程启动");
            ExecutionEntityImpl executionEntity =getExcutionEntity(event);
            uniWFService.callbackWFProcessStarted(event,executionEntity);
        }
        //实例结束
        if(eventType == ActivitiEventType.PROCESS_COMPLETED){
            System.out.println("流程结束");
            ExecutionEntityImpl executionEntity =getExcutionEntity(event);
            uniWFService.callbackWFProcessCompleted(event,executionEntity);
        }
        //实例取消
        if(eventType == ActivitiEventType.PROCESS_CANCELLED){

            System.out.println("流程终止");
            ExecutionEntityImpl executionEntity =getExcutionEntity(event);
            uniWFService.callbackWFProcessCancelled(event,executionEntity);
        }
        //待办创建
        if(eventType == ActivitiEventType.TASK_CREATED){

            System.out.println("创建任务");
            TaskEntityImpl taskEntity=getTaskEntity(event);
            uniWFService.callbackWFTaskCreated(event,taskEntity);
        }
        //待办分配
        if(eventType == ActivitiEventType.TASK_ASSIGNED){

            System.out.println("分配任务");
            TaskEntityImpl taskEntity=getTaskEntity(event);
            uniWFService.callbackWFTaskAssigned(event,taskEntity);
        }
        //待办完成
        if(eventType == ActivitiEventType.TASK_COMPLETED){
            System.out.println("完成任务");
            TaskEntityImpl taskEntity=getTaskEntity(event);
            uniWFService.callbackWFTaskCompleted(event,taskEntity);
        }
    }

    /**
     * 获取当前待办任务
     * @param event
     * @return
     */
    private TaskEntityImpl  getTaskEntity(ActivitiEvent event){
        TaskEntityImpl taskEntity = null;
        if( event instanceof ActivitiEntityEventImpl){
            ActivitiEntityEventImpl activitiEntityEvent= (ActivitiEntityEventImpl) event;
            Object entity = activitiEntityEvent.getEntity();
            if(entity instanceof  TaskEntityImpl){
                taskEntity= (TaskEntityImpl) entity;
            }
        }
        return taskEntity;
    }


    /**
     * 获取当前流程步骤
     * @param event
     * @return
     */
    private UserTask getUserTask(ActivitiEvent event){
        UserTask userTask=null;
        if(event instanceof ActivitiEventImpl){
            ActivitiActivityEventImpl activiti = (ActivitiActivityEventImpl) event;
            Process process = repositoryService.getBpmnModel(event.getProcessDefinitionId()).getMainProcess();
            FlowElement flowElement= process.getFlowElement(activiti.getActivityId());
            if(flowElement instanceof UserTask){
                userTask= (UserTask) flowElement;
            }
        }
        return userTask;
    }

    /**
     * 获取当前流程执行参数
     * @param event
     * @return
     */
    private ExecutionEntityImpl getExcutionEntity(ActivitiEvent event){

        ExecutionEntityImpl  executionEntity=null;
        if( event instanceof ActivitiProcessStartedEventImpl){
            ActivitiProcessStartedEventImpl startedEvent= (ActivitiProcessStartedEventImpl) event;
            Object entity = startedEvent.getEntity();
            if(entity instanceof ExecutionEntityImpl){
                executionEntity= (ExecutionEntityImpl) entity;
            }
        }
        return executionEntity;
    }

    @Override
    public boolean isFailOnException() {
        return false;
    }

}
