package com.highdatas.mdm.service.act.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.highdatas.mdm.process.canvas.ProcessDiagramGenerator;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.ReadOnlyProcessDefinition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Service
public class RuntimeServiceImpl extends BaseServiceImpl implements com.highdatas.mdm.service.act.RuntimeService{
	@Autowired
	RuntimeService service;
	@Autowired
	RepositoryService repositoryService;
	@Autowired
	TaskService taskService;
	@Autowired
	HistoryService historyService;



	public void getList() {
		ProcessInstanceQuery query = service.createProcessInstanceQuery();
		List<ProcessInstance> instanceList = query.list();
		//resultPool.addValue(null, instanceList, new ProcessInstanceWriter());
	}
	@Override
	public void deleteProcess(String processId) {
		service.deleteProcessInstance(processId, "终止流程");
	}


	public void startProcess(String processId) {
		ProcessInstance process = service.startProcessInstanceById(processId);
	}
	
	public void suspendProcess(String processId) {
		service.suspendProcessInstanceById(processId);
	}
	
	public void activateProcess(String processId) {
		service.activateProcessInstanceById(processId);
	}
	
	public void getDiagram(String processId, HttpServletResponse response) {
		Task task = taskService.createTaskQuery().processInstanceId(processId).singleResult();
		if (task ==null) {
			return ;
		}
		InputStream resource = null;
		try {
			ProcessDefinition singleResult = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
			Model model = repositoryService.createModelQuery().deploymentId(singleResult.getDeploymentId()).singleResult();
			JsonNode editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(model.getId()));
			BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
			BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);
			List<String> activeActivityIds = service.getActiveActivityIds(task.getExecutionId());
			ProcessDiagramGenerator diagramGenerator = new ProcessDiagramGenerator();
			resource = diagramGenerator.generateDiagram(bpmnModel, "png",activeActivityIds,activeActivityIds, "宋体","宋体" ,null, null,0);
			response.setHeader("Content-Type", "image/png");
			OutputStream outputStream = response.getOutputStream();
			byte[] b = new byte[1024];
			int len;
			while ((len = resource.read(b, 0, 1024)) != -1) {
				outputStream.write(b, 0, len);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (resource != null) {
				try {
					resource.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public void getActivitiProccessImage(String processId, HttpServletResponse response) {
		try {
			if (StringUtils.isEmpty(processId)) {
				return;
			}
			
			List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).list();
			if (list.size() == 0) {
				return;
			}
			HistoricProcessInstance processInstance = list.get(0);

			if (processInstance != null) {
	            ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
	            		.getDeployedProcessDefinition(processInstance.getProcessDefinitionId());
	            List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
	                    .processInstanceId(processId).orderByHistoricActivityInstanceId().asc().list();
	            List<String> executedActivityIdList = new ArrayList<String>();
	            int index = 1;
	            
	            for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
	                executedActivityIdList.add(activityInstance.getActivityId());                
	                index++;
	            }
	            
	            List<String> flowIds = new ArrayList<String>();
	            flowIds = getHighLightedFlows(processDefinition, historicActivityInstanceList);
	            BpmnModel bpmnModel = repositoryService
	                    .getBpmnModel(processInstance.getProcessDefinitionId());
//	            ProcessDiagramGenerator pec = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator();
	            com.highdatas.mdm.process.canvas.ProcessDiagramGenerator pec = new com.highdatas.mdm.process.canvas.ProcessDiagramGenerator();
	            
	            InputStream imageStream = pec.generateDiagram(bpmnModel, "png", executedActivityIdList, flowIds,"宋体","微软雅黑",null,null,2.0);
	            response.setContentType("image/png");
	            OutputStream os = response.getOutputStream();
	            int bytesRead = 0;
	            byte[] buffer = new byte[1024*8];
	            
	            while ((bytesRead = imageStream.read(buffer, 0, 1024*8)) != -1) {
	                os.write(buffer, 0, bytesRead);
	            }
	            os.close();
	            imageStream.close();
	        }        
	    } 
		catch (Exception e) {  
	    	e.printStackTrace();
	    }
	}
	
	public List<String> getHighLightedFlows(ProcessDefinitionEntity processDefinitionEntity,List<HistoricActivityInstance> historicActivityInstances) { 
		List<String> highFlows = new ArrayList<String>();  
		
		for (int i = 0; i < historicActivityInstances.size() - 1; i++) {
		    ActivityImpl activityImpl = processDefinitionEntity.findActivity(historicActivityInstances.get(i).getActivityId());     
		    List<ActivityImpl> sameStartTimeNodes = new ArrayList<ActivityImpl>();    
		    ActivityImpl sameActivityImpl1 = processDefinitionEntity.findActivity(historicActivityInstances.get(i + 1).getActivityId());
	        sameStartTimeNodes.add(sameActivityImpl1); 
	        
	        for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) {        
	    		HistoricActivityInstance activityImpl1 = historicActivityInstances.get(j);       
	    		HistoricActivityInstance activityImpl2 = historicActivityInstances.get(j + 1);       
	    		if (activityImpl1.getStartTime().equals(activityImpl2.getStartTime())) {
	    			ActivityImpl sameActivityImpl2 = processDefinitionEntity.findActivity(activityImpl2.getActivityId());           
	    			sameStartTimeNodes.add(sameActivityImpl2);           
	    		} 
	    		else {          
	    			break;          
	    		}   
	        }       
	        List<PvmTransition> pvmTransitions = activityImpl.getOutgoingTransitions(); 
	        
	        for (PvmTransition pvmTransition : pvmTransitions) {
	        	ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition.getDestination();      
	        	if (sameStartTimeNodes.contains(pvmActivityImpl)) {               
	        		highFlows.add(pvmTransition.getId());           
	        	}        
	        }    
		}    
		return highFlows;
	}
	public ActivityImpl getCurrentAcitivity(String processDefinitionId) {
		Execution execution = service.createExecutionQuery().processDefinitionId(processDefinitionId).singleResult();  
		String activityId = execution.getActivityId();  
		ActivityImpl currentActivity = queryTargetActivity(activityId);  
		log.debug(currentActivity.getId()+""+currentActivity.getProperty("name"));  
		return currentActivity;  
	}

	 public ActivityImpl  queryTargetActivity(String id){  
	    ReadOnlyProcessDefinition deployedProcessDefinition = (ProcessDefinitionEntity)((RepositoryServiceImpl)repositoryService).getDeployedProcessDefinition("ziyouliu:1:4");  
	    @SuppressWarnings("unchecked")
	    
		List<ActivityImpl> activities = (List<ActivityImpl>) deployedProcessDefinition.getActivities();  
	    for (ActivityImpl activityImpl : activities) {  
	        if(activityImpl.getId().equals(id)){  
	            return activityImpl;  
	        }  
	     }  
	    return null;  
	 }  

}