package com.leanwo.activiti.service.base.impl;

import java.util.List;

import javax.inject.Inject;

import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.leanwo.activiti.dto.BaseResponse;
import com.leanwo.activiti.dto.base.TaskDefineDto;
import com.leanwo.activiti.dto.base.TaskInstanceSaveRequest;
import com.leanwo.activiti.dto.base.TaskInstanceStatus;
import com.leanwo.activiti.dto.base.TaskInstanceUpdateRequest;
import com.leanwo.activiti.dto.base.TaskType;
import com.leanwo.activiti.service.base.ProcessReportEngine;
import com.leanwo.activiti.service.base.QuartzEngine;
import com.leanwo.activiti.service.base.TaskDefineService;
import com.leanwo.activiti.service.base.TokenService;
import com.leanwo.activiti.util.LoginContext;
import com.leanwo.activiti.util.LoginContextUtil;
import com.leanwo.activiti.util.TokenUtil;

/**
 * 流程报表自动执行引擎
 * 
 * @author YangZhiJie 20190401
 *
 */
public class ProcessReportEngineImpl extends Thread implements ProcessReportEngine {

	private static Logger logger = LoggerFactory.getLogger(ProcessReportEngineImpl.class);

	@Inject
	private TaskDefineService taskDefineService;

	@Inject
	private QuartzEngine quartzEngine;

	private Long accountId;

	private boolean enable;

	@Inject
	private TokenService tokenService;

	/**
	 * 
	 * @param accountId
	 *            账套Id
	 * @param enable
	 *            是否启动流程报表自动执行引擎
	 */
	public ProcessReportEngineImpl(Long accountId, Boolean enable) {
		this.accountId = accountId;
		this.enable = enable;
	}

	@Override
	public void run() {
		LoginContext loginContext = new LoginContext();
		loginContext.setAccountId(accountId);
		String tempToken = tokenService.generateTempToken();
		TokenUtil.setToken(tempToken);
		LoginContextUtil.setLoginContext(loginContext);
		while (true) {
			try {
				List<TaskDefineDto> taskDefineDtos = taskDefineService.list(TaskType.PROCESS_REPORT);
				String message = String.format("账套%d共计查询到%d条流程报表定时执行任务。", accountId,
						taskDefineDtos == null ? 0 : taskDefineDtos.size());
				logger.info(message);
				if (taskDefineDtos != null) {
					for (int i = 0; i < taskDefineDtos.size(); i++) {
						TaskDefineDto taskDefineDto = taskDefineDtos.get(i);
						try {
							quartzEngine.addProcessJob(accountId, taskDefineDto);
						} catch (SchedulerException e) {
							logger.error("流程报表定时任务添加失败。" + taskDefineDto.toString(), e);
						}
					}
				}
			} catch (Exception ex) {
				logger.error("流程报表定时任务查询失败，流程报表定时任务引擎不能启动", ex);
			}

			try {
				// 每隔5分钟，更新一次流程报表的定义
				Thread.sleep(5 * 60 * 1000L);
			} catch (InterruptedException e) {
				logger.error("", e);
			}
		}
	}

	@Override
	public void init() {
		if (this.enable == false) {
			logger.info("设置了流程报表自动执行引擎不启动。");
			return;
		}

		LoginContext loginContext = new LoginContext();
		loginContext.setAccountId(accountId);
		LoginContextUtil.setLoginContext(loginContext);

		try {
			// 必须先开始,否则触发器不执行任务
			quartzEngine.start();
		} catch (SchedulerException e) {
			logger.error("流程报表定时任务引擎启动失败", e);
		}

		this.start();
	}

	@Override
	public BaseResponse addJob(TaskDefineDto taskDefineDto) throws SchedulerException {
		BaseResponse baseResponse = new BaseResponse();
		try {
			Long accountId = LoginContextUtil.getLoginContext().getAccountId();
			if (enable) {
				quartzEngine.addProcessJob(accountId, taskDefineDto);
				baseResponse.setErrorCode(0);
				baseResponse.setErrorMessage("添加成功");
			} else {
				baseResponse.setErrorCode(1);
				baseResponse.setErrorMessage("未设置流程报表自动启动");
			}
		} catch (SchedulerException e) {
			baseResponse.setErrorCode(-1);
			baseResponse.setErrorMessage("添加失败:" + e.getMessage());
		}
		return baseResponse;

	}

	@Override
	public BaseResponse deleteJob(TaskDefineDto taskDefineDto) throws SchedulerException {
		BaseResponse baseResponse = new BaseResponse();
		try {
			Long accountId = LoginContextUtil.getLoginContext().getAccountId();
			if (enable) {
				quartzEngine.deleteProcessJob(accountId, taskDefineDto);
				baseResponse.setErrorCode(0);
				baseResponse.setErrorMessage("删除成功");
			} else {
				baseResponse.setErrorCode(1);
				baseResponse.setErrorMessage("未设置流程报表自动启动");
			}
		} catch (SchedulerException e) {
			baseResponse.setErrorCode(-1);
			baseResponse.setErrorMessage("删除失败:" + e.getMessage());
		}
		return baseResponse;
	}

	@Override
	public BaseResponse addTaskInstance(Long timeSerialNumber, TaskDefineDto taskDefineDto) {
		TaskInstanceSaveRequest taskInstanceSaveRequest = new TaskInstanceSaveRequest();
		taskInstanceSaveRequest.setTimeSerialNumber(timeSerialNumber);
		taskInstanceSaveRequest.setTaskDefineId(taskDefineDto.getId());
		taskInstanceSaveRequest.setClientId(taskDefineDto.getClientId());
		taskInstanceSaveRequest.setUserId(taskDefineDto.getUserId());
		return taskDefineService.addTaskInstance(taskInstanceSaveRequest);
	}

	@Override
	public BaseResponse updateTaskInstance(Long timeSerialNumber, String result, TaskInstanceStatus taskInstanceStatus,
			TaskDefineDto taskDefineDto) {
		TaskInstanceUpdateRequest taskInstanceUpdateRequest = new TaskInstanceUpdateRequest();
		taskInstanceUpdateRequest.setTimeSerialNumber(timeSerialNumber);
		taskInstanceUpdateRequest.setTaskDefineId(taskDefineDto.getId());
		taskInstanceUpdateRequest.setOperationResult(result);
		taskInstanceUpdateRequest.setTaskInstanceStatus(taskInstanceStatus);
		taskInstanceUpdateRequest.setClientId(taskDefineDto.getClientId());
		taskInstanceUpdateRequest.setUserId(taskDefineDto.getUserId());
		return taskDefineService.updateTaskInstance(taskInstanceUpdateRequest);
	}

}
