package com.blueland.bpm.engine.core.service.impl;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.blueland.bpm.engine.core.executor.ProcessExecutor;
import com.blueland.bpm.engine.core.model.ExceptionErrorCode;
import com.blueland.bpm.engine.core.model.ProcessExeErrorShare;
import com.blueland.bpm.engine.core.model.ProcessInputModel;
import com.blueland.bpm.engine.core.model.ProcessInstanceModel;
import com.blueland.bpm.engine.core.model.TaskEntityDataShare;
import com.blueland.bpm.engine.core.service.AbstractServiceHelper;
import com.blueland.bpm.engine.core.service.ProcessConfigService;
import com.blueland.bpm.engine.core.service.ProcessExecuteService;
import com.blueland.bpm.engine.core.service.ProcessExecutorFactory;
import com.blueland.bpm.engine.util.JsonUtil;
import com.blueland.bpm.engine.util.ProcessDefinitionUtils;
import com.blueland.bpm.engine.util.WorkFlowException;
import com.blueland.bpm.log.model.ProcessErrorLog;
import com.blueland.bpm.log.service.ProcessErrorLogManager;
/**
 * 流程执行Service
 * @version:  1.0
 * @author lw 
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
public class ProcessExecuteServiceImpl   extends AbstractServiceHelper implements ProcessExecuteService {
	protected Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	private ProcessExecutorFactory processExecutorFactory;
	@Autowired
	private ProcessErrorLogManager processErrorLogManager;
	@Autowired
	ProcessConfigService processConfigService;

	/**
	 * 流程执行接口
	 * 
	 * @param processInputModel
	 * @return Map<String,Object>
	 */
	@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
	public Map<String, Object> nextExecute(ProcessInputModel processInputModel) {
		String jsonMsg = JsonUtil.convertToJson(processInputModel);
		logger.info("流程执行前输入参数,processInputModel:{}", new Object[] { processInputModel });
		logger.info("流程执行前消息包,processInputModelJson:{}", new Object[] { jsonMsg });

		ProcessInstanceModel processInstanceModel = null;
		String executeStatus = "";
		String executeErrorMsg = "";
		ExceptionErrorCode exceptionErrorCode = null;
		try {
			// 初始化
			init(processInputModel);
			processInstanceModel = execute(processInputModel);
			/*
			 * executeStatus = processInstanceModel != null ? EXECUTE_STATUS_SUCCESS :
			 * EXECUTE_STATUS_ERROR;
			 */
			executeStatus = EXECUTE_STATUS_SUCCESS;
		} catch (Exception e) {
			if (e instanceof WorkFlowException) {
				WorkFlowException wfe = ((WorkFlowException) e).getWorkFlowException(e);
				if (wfe == null) {
					wfe = (WorkFlowException) e;
				}
				exceptionErrorCode = wfe.getExceptionErrorCode();
				executeErrorMsg = wfe.getWebShowErrorMessage();
			} else {
				executeErrorMsg = String.format("标题为[%s]的流程执行失败,processInputModel对象数据为[%s]",
						processInputModel.getWf_procTitle(), processInputModel);
				exceptionErrorCode = ExceptionErrorCode.B2050;
			}
			processErrorLogManager.save(buildProcessErrorLog(processInputModel, executeErrorMsg, jsonMsg));
			logger.error(executeErrorMsg, e);
			executeStatus = EXECUTE_STATUS_ERROR;
		}
		if (processInstanceModel != null) {
			processInstanceModel.setProcessInputModel(processInputModel);
		}
		Map<String, Object> resultMap = new HashMap<String, Object>();
		// 设置返回参数
		resultMap.put("executeStatus", executeStatus);
		resultMap.put("processInstanceModel", processInstanceModel);
		resultMap.put("executeErrorCode", exceptionErrorCode);
		resultMap.put("executeErrorMsg", executeErrorMsg);
		logger.info("流程执行后输出参数:resultMap:" + resultMap);
		if (executeStatus == EXECUTE_STATUS_ERROR) {
			ProcessExeErrorShare.setProcessExeErrorData(resultMap);
		}else {
			//流程执行成功才记录运行日志,失败已经记录了错误日志了
			try {
				ProcessErrorLog infoLog = buildProcessInfoLog(processInstanceModel, jsonMsg);
				String resultJsonMsg = JsonUtil.convertToJson(processInstanceModel);
				infoLog.setErrorMsg(resultJsonMsg);
				processErrorLogManager.save(infoLog);
			} catch (Exception e) {
				logger.error("保存流程运行日志失败，jsonMsg：" + jsonMsg, e);
			}
		}
		return resultMap;
	}
	/**
	 * 流程执行初始化
	 * @param processInputModel
	 */
	private void init(ProcessInputModel processInputModel){
		//将ActivityReceiverModel对象(usercode+orgid)转换成字符串接人人userId
		ProcessDefinitionUtils.convertWf_receivers(processInputModel);
	}
	/**
	 * 流程执行
	 * @param processInputModel
	 * @return
	 */
	private ProcessInstanceModel execute(ProcessInputModel processInputModel) {
		ProcessExecutor processExecuteCmd = processExecutorFactory
				.buildProcessExecutor(processInputModel.getWf_actionType());
		if (processExecuteCmd == null) {
			throw new WorkFlowException(ExceptionErrorCode.B2050,
					"流程执行时无法在ProcessInputModel类中找到对应的wf_actionType操作");
		}
		ProcessInstanceModel processInstanceModel= processExecuteCmd.execute(processInputModel);
	    logger.info("原待办数据:"+processInstanceModel.getNextActivity());
	    logger.info("新待办数据:"+TaskEntityDataShare.getTask());
	    logger.info("已办数据:"+TaskEntityDataShare.getHisTask());
	    return processInstanceModel;
	}
	
	
}
