package com.gaowj.business.procinstance;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
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.repository.ProcessDefinition;
import org.activiti.engine.task.Task;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.apache.ibatis.session.RowBounds;

import com.gaowj.business.ProcinstanceBusiness;
import com.gaowj.business.exception.ActivitiException;
import com.gaowj.business.exception.BusinessException;
import com.gaowj.business.formtable.formtableDAO;
import com.gaowj.business.procdefinition.procdefinitionDAO;
import com.gaowj.business.system.SystemBackDAO;
import com.gaowj.business.util.Page;
import com.gaowj.business.util.PropUtil;
import com.gaowj.business.util.SessionUtil;
import com.gaowj.business.utils.ActivitiTools;
import com.gaowj.business.utils.model.ActivitiOptEnum;
import com.gaowj.business.utils.model.ActivitiResultEnum;

public class ProcinstanceBusinessImpl implements ProcinstanceBusiness {

	private procinstanceDAO procinstanceDAO;

	private procdefinitionDAO procdefinitionDAO;

	private formtableDAO formtableDAO;

	private RuntimeService runtimeService;

	private TaskService taskService;

	private HistoryService historyService;

	private RepositoryService repositoryService;

	private SystemBackDAO systemBackDAO;

	public RuntimeService getRuntimeService() {
		return runtimeService;
	}

	public void setRuntimeService(RuntimeService runtimeService) {
		this.runtimeService = runtimeService;
	}

	public procdefinitionDAO getProcdefinitionDAO() {
		return procdefinitionDAO;
	}

	public void setProcdefinitionDAO(procdefinitionDAO procdefinitionDAO) {
		this.procdefinitionDAO = procdefinitionDAO;
	}

	public formtableDAO getFormtableDAO() {
		return formtableDAO;
	}

	public void setFormtableDAO(formtableDAO formtableDAO) {
		this.formtableDAO = formtableDAO;
	}

	public procinstanceDAO getProcinstanceDAO() {
		return procinstanceDAO;
	}

	public void setProcinstanceDAO(procinstanceDAO procinstanceDAO) {
		this.procinstanceDAO = procinstanceDAO;
	}

	public TaskService getTaskService() {
		return taskService;
	}

	public void setTaskService(TaskService taskService) {
		this.taskService = taskService;
	}

	public HistoryService getHistoryService() {
		return historyService;
	}

	public void setHistoryService(HistoryService historyService) {
		this.historyService = historyService;
	}

	public RepositoryService getRepositoryService() {
		return repositoryService;
	}

	public void setRepositoryService(RepositoryService repositoryService) {
		this.repositoryService = repositoryService;
	}

	public SystemBackDAO getSystemBackDAO() {
		return systemBackDAO;
	}

	public void setSystemBackDAO(SystemBackDAO systemBackDAO) {
		this.systemBackDAO = systemBackDAO;
	}

	@Override
	public Map<String, Object> insert_proc_instance(Map<String, Object> entity) throws ActivitiException,BusinessException {
		// 流程定义id
		String procId = entity.get("PROCID").toString();
		// 实时的表单模板id
		String formModelId = entity.get("FORM_MODEL_ID").toString();
		// 删除除业务数据外的所有字段
		entity.remove("PROCID");
		entity.remove("FORM_MODEL_ID");
		ActivitiResultEnum activitiResultEnum = ActivitiTools.initNotStart(procId, formModelId, entity);
		switch (activitiResultEnum) {
		case OK:
			break;
		default:
			throw new ActivitiException(activitiResultEnum.getMsg());
		}
		return entity;
	}

	@Override
	public Map<String, Object> insert_proc_instance_next(Map<String, Object> entity) throws ActivitiException,BusinessException {
		// 流程定义id
		String procId = entity.get("PROCID").toString();
		// 实时的表单模板id
		String formModelId = entity.get("FORM_MODEL_ID").toString();
		// 删除除业务数据外的所有字段
		entity.remove("PROCID");
		entity.remove("FORM_MODEL_ID");
		ActivitiResultEnum activitiResultEnum = ActivitiTools.initStart(procId, formModelId, entity);
		switch (activitiResultEnum) {
		case OK:
			break;
		default:
			throw new ActivitiException(activitiResultEnum.getMsg());
		}

		return entity;
	}

	@Override
	public Map<String, Object> update_proc_instance(Map<String, Object> entity) throws ActivitiException,BusinessException {
		ActivitiResultEnum activitiResultEnum = ActivitiTools.save(entity, ActivitiOptEnum.SAVE);
		switch (activitiResultEnum) {
		case OK:
			break;
		default:
			throw new ActivitiException(activitiResultEnum.getMsg());
		}
		return entity;
	}

	@Override
	public Map<String, Object> update_proc_instance_next(Map<String, Object> entity) throws ActivitiException,BusinessException {
		ActivitiResultEnum activitiResultEnum = ActivitiTools.save(entity, ActivitiOptEnum.SAVE_AND_NEXT);
		switch (activitiResultEnum) {
		case OK:
			break;
		default:
			throw new ActivitiException(activitiResultEnum.getMsg());
		}
		return entity;
	}

	@Override
	public void delete_proc_instance(List<String> list) throws BusinessException {
		// 查询流程实例表
		Map<String, Object> query = new HashMap<String, Object>();
		query.put("UUIDIN", list);
		List<Map<String, Object>> listInstance = procinstanceDAO.list_proc_instance_all(query);
		// 获取业务主键id
		List<Map<String, Object>> listBusiness = new ArrayList<Map<String, Object>>();
		for (Map<String, Object> m : listInstance) {
			Map<String, Object> business = new HashMap<String, Object>();
			business.put("UUID", m.get("BUSINESS_ID"));
			business.put("TABLE_NAME", m.get("TABLE_NAME"));
			listBusiness.add(business);
		}
		// 整理业务表id,以表名为key,listuuid为value
		Map<String, List<String>> listBusinessUuidList = new HashMap<String, List<String>>();
		for (Map<String, Object> m : listBusiness) {
			List<String> listUuid = null;
			if (listBusinessUuidList.get(m.get("TABLE_NAME")) == null) {
				listUuid = new ArrayList<String>();
				listBusinessUuidList.put((String) m.get("TABLE_NAME"), listUuid);
			} else {
				listUuid = listBusinessUuidList.get(m.get("TABLE_NAME"));
			}
			listUuid.add(m.get("UUID").toString());
		}
		// 根据业务主键id和表名删除具体的业务数据
		for (String tableName : listBusinessUuidList.keySet()) {
			Map<String, Object> deleteParams = new HashMap<String, Object>();
			deleteParams.put("TABLE_NAME", tableName);
			deleteParams.put("list", listBusinessUuidList.get(tableName));
			procinstanceDAO.delete_proc_instance_business(deleteParams);
		}
		// 删除实例表
		procinstanceDAO.delete_proc_instance(list);
	}

	@Override
	public Page<Map<String, Object>> list_proc_instance(int pageNo, int pageSize, Map<String, Object> query) throws BusinessException {
		/*
		 * List<Task>
		 * listTask=taskService.createTaskQuery().taskAssignee(SessionUtil.
		 * getCode()).list(); System.out.println(listTask.size());
		 */
		// 只查询当前登陆人的实例列表
		query.put("CREATE_ID", SessionUtil.getCode());
		String procdefinitionUuid = null;
		String tableName = null;
		boolean notExist = false;
		
		if(query.get("SERACH_DATA")!=null&&!"".equals(query.get("SERACH_DATA"))){
			query.put("SERACH_DATA","%"+query.get("SERACH_DATA")+"%");
		}
		
		if (query.get("PROCDEFINITION_UUID") != null && !"".equals(query.get("PROCDEFINITION_UUID"))) {
			procdefinitionUuid = query.get("PROCDEFINITION_UUID").toString();
			query.remove("PROCDEFINITION_UUID");
			// 通过流程定义id获取表名
			Map<String, Object> query2 = new HashMap<String, Object>();
			query2.put("UUID", procdefinitionUuid);
			tableName = procdefinitionDAO.list_procde_finition(query2).get(0).get("TABLE_NAME").toString();
		}
		// 计算起始记录
		int pageStart = (pageNo - 1) * pageSize;

		// 获取列表
		List<Map<String, Object>> items = null;
		if (tableName != null) {
			query.put("tableName", tableName);
			query.put("PROC_DEFINITION_ID", procdefinitionUuid);
			try {
				query.put("lcyq_table_db", PropUtil.getValue("lcyq_table_db", "quartz_service", ""));
				items = procinstanceDAO.list_proc_instance(new RowBounds(pageStart, pageSize), query);
			} catch (Exception e) {
				if (e.getMessage().indexOf("doesn't exist") != -1) {
					// 如果有XX不存在字样,说明当前需要查询的表不存在,则直接设置为空list
					items = new ArrayList<Map<String, Object>>();
					notExist = true;
				}
			}
		} else {
			items = procinstanceDAO.list_proc_instance_all(new RowBounds(pageStart, pageSize), query);
		}

		// 获取列表个数
		int count = 0;
		if (!notExist) {
			// 如果表存在,则继续查询数量
			query.put("lcyq_table_db", PropUtil.getValue("lcyq_table_db", "quartz_service", ""));
			count = listCount_proc_instance(query);
		}

		// 创建分页对象
		Page<Map<String, Object>> page = new Page<Map<String, Object>>();
		page.setStart(pageStart);
		page.setLimit(pageSize);
		page.setCount(count);
		page.setItems(items);

		return page;
	}

	@Override
	public List<Map<String, Object>> list_proc_instance_history(String processInstanceId) throws BusinessException {
		List<HistoricActivityInstance> listHistoricActivityInstance = historyService // 历史相关Service
				.createHistoricActivityInstanceQuery() // 创建历史活动实例查询
				.processInstanceId(processInstanceId) // 执行流程实例id
				// .finished()
				.orderByHistoricActivityInstanceStartTime().asc().list();

		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		List<String> listAssignee = new ArrayList<String>();
		for (HistoricActivityInstance hai : listHistoricActivityInstance) {
			if (!"userTask".equals(hai.getActivityType())) {
				// 只显示userTask类型
				continue;
			}
			
			if (hai.getAssignee() != null) {
				listAssignee.add(hai.getAssignee());
			}
			Map<String, Object> entry = new HashMap<String, Object>();
			entry.put("ACTIVITY_NAME", hai.getActivityName());
			entry.put("ASSIGNEE", hai.getAssignee() == null ? "" : hai.getAssignee());
			entry.put("START_TIME", hai.getStartTime());
			entry.put("END_TIME", hai.getEndTime() == null ? "" : hai.getEndTime());
			list.add(entry);
		}

		Map<String, Object> query = new HashMap<String, Object>();
		query.put("CODE_IN", listAssignee);
		List<Map<String, Object>> items = systemBackDAO.listLoginUserInfo(query);

		outer: for (Map<String, Object> m : list) {
			for (Map<String, Object> user : items) {
				if (m.get("ASSIGNEE") != null && !"".equals(m.get("ASSIGNEE"))) {
					if (m.get("ASSIGNEE").equals(user.get("CODE"))) {
						m.put("ASSIGNEE", user.get("EMNAME"));
						continue outer;
					}
				}
			}
		}
		return list;
	}

	@Override
	public List<Map<String, Object>> list_proc_instance(Map<String, Object> query) throws BusinessException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int listCount_proc_instance(Map<String, Object> query) throws BusinessException {
		if (query.get("tableName") == null) {
			return procinstanceDAO.listCount_proc_instance_all(query);
		}
		return procinstanceDAO.listCount_proc_instance(query);
	}

	@Override
	public InputStream viewPic(String instanceId, StringBuffer filename) throws BusinessException {
		InputStream imageStream = null;
		// 获取历史流程实例
		HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(instanceId).singleResult();
		if (historicProcessInstance == null) {
			throw new BusinessException("Instance doesn't exist.");
		} else {
			// 获取图片资源名称
			List<String> list = repositoryService.getDeploymentResourceNames(historicProcessInstance.getProcessDefinitionId());
			// 定义图片资源的名称(一个流程定义,默认都有两个资源文件,一个是png,一个是xml,这里只获取png)
			String resourceName = "";
			if (list != null && list.size() > 0) {
				for (String name : list) {
					if (name.indexOf(".png") >= 0) {
						resourceName = name;
					}
				}
			}
			filename.append(resourceName);
			// 获取流程历史中已执行节点,并按照节点在流程中执行先后顺序排序
			List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery().processInstanceId(instanceId).orderByHistoricActivityInstanceId().asc().list();

			// 已执行的节点ID集合
			List<String> executedActivityIdList = new ArrayList<String>();
			@SuppressWarnings("unused")
			int index = 1;
			for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
				executedActivityIdList.add(activityInstance.getActivityId());
				index++;
			}

			// 获取流程定义对象
			ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(historicProcessInstance.getProcessDefinitionId()).singleResult();
			String xmlName = processDefinition.getResourceName();
			// 获取流程资源
			InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), xmlName);
			// 创建转换对象
			BpmnXMLConverter converter = new BpmnXMLConverter();
			// 读取xml文件
			XMLInputFactory factory = XMLInputFactory.newInstance();
			XMLStreamReader reader = null;
			try {
				reader = factory.createXMLStreamReader(inputStream);
			} catch (XMLStreamException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			// 将xml文件转换成BpmnModel
			BpmnModel bpmnModel = converter.convertToBpmnModel((XMLStreamReader) reader);
			// BpmnModel bpmnModel =
			// this.repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
			// imageStream = new
			// DefaultProcessDiagramGenerator().generateDiagram(bpmnModel,
			// "png", executedActivityIdList);
			imageStream = new DefaultProcessDiagramGenerator().generateDiagram(bpmnModel, "png", executedActivityIdList, Collections.<String>emptyList(), "宋体", "宋体", null, 1.0);

		}
		return imageStream;
	}
}