package com.leanwo.activiti.listener.base;

import java.util.ArrayList;
import java.util.List;

import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.ExecutionListener;
import org.activiti.engine.delegate.Expression;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.leanwo.activiti.dto.base.LeaderUserDto;
import com.leanwo.activiti.exception.WorkflowException;
import com.leanwo.activiti.service.base.impl.ProdogServer;
import com.leanwo.activiti.service.base.impl.UserPreference;
import com.leanwo.activiti.util.SpringUtil;
import com.leanwo.activiti.util.StringUtil;


/**
 * 多实例任务（主管）创建监听器
 * <ul>
 * 		<li>获取流程发起人</li>
 * 		<li>获取流程发起人的上级主管(有好几级)</li>
 * 		<li>设置审批人</li>
 * </ul>.
 *
 * @author YangZhiJie
 */
public class MultiInstanceUserTaskByDirectorExecutionListener implements ExecutionListener{
	
	/**  */
	private static Logger logger = LoggerFactory.getLogger(MultiInstanceUserTaskByDirectorExecutionListener.class);

	/**  任务接受人(String). */
	private Expression assignListVariableName;

	/**  1:直接主管, 2:第2级主管, 3: 第3级主管. */
	private Expression leaderLevel;
	
	/**  找不到主管时，由上级主管代审批. */
	private Expression useDirectorProxy;

	/** 节点名称. */
	private Expression nodeName;
	
	/**
	 * 
	 *
	 * @param execution 
	 */
	@Override
	public void notify(DelegateExecution execution) {
		String assignListName = assignListVariableName.getExpressionText();
		String leaderLevelText = leaderLevel.getExpressionText();
		String useDirectorProxyText = useDirectorProxy.getExpressionText();
		String node = nodeName.getExpressionText();

		if(StringUtil.isEmpty(assignListName) || StringUtil.isEmpty(leaderLevelText)
				|| StringUtil.isEmpty(useDirectorProxyText)) {
			throw new WorkflowException(String.format("多实例任务(%s)未定义变量assignListVariableName、leaderLevel 和 useDirectorProxy。", node));
		}
		
		Integer leaderLevel = Integer.parseInt(leaderLevelText);
		Boolean useDirectorProxy = Boolean.parseBoolean(useDirectorProxyText);
		
		// 1. 获取流程发起人
		Long createUserId = (Long)execution.getVariable(UserPreference.CREATE_USER_ID);
		
		if(createUserId == null) {
			throw new WorkflowException("找不到流程发起人：" + UserPreference.CREATE_USER_ID);
		}
		
		ProdogServer prodogServer = SpringUtil.getBean(ProdogServer.class.getName());
		
		List<LeaderUserDto> userDtos = prodogServer.listLeaderUser(createUserId);
		
		List<LeaderUserDto> targetLeaderUserDtos = new ArrayList<LeaderUserDto>();
		
		// 查找直接主管
		if(userDtos != null) {
			for(LeaderUserDto leaderUserDto : userDtos) {
				if(leaderUserDto.getLeaderLevel() == leaderLevel) {
					targetLeaderUserDtos.add(leaderUserDto);
				}
			}
		}
		
		int leaderLevelCurrent = leaderLevel;
		
		// 选定层级的主管找不到，此时找上级主管
		if(userDtos != null && targetLeaderUserDtos.size() == 0 && useDirectorProxy) {
			while(targetLeaderUserDtos.size() == 0 && leaderLevelCurrent++ <= 5) {
				for(LeaderUserDto leaderUserDto : userDtos) {
					if(leaderUserDto.getLeaderLevel() == leaderLevelCurrent) {
						targetLeaderUserDtos.add(leaderUserDto);
					}
				}
			}
		}
		
		// 审批人为空时抛出异常
		if(targetLeaderUserDtos.size() == 0) {
			String message = String.format("主管领导(第%d级主管)审批节点(%s)，审批发起人无主管领导，请设置审批发起人所在部门的主管。", leaderLevel, node);
			throw new WorkflowException(message);
		}
		
		// 提前设置好审批人
		List<String> userIdStrings = new ArrayList<String>();
		userDtos.forEach(userDto -> {
			userIdStrings.add(userDto.getId().toString());
		});
		execution.setVariable(assignListName, userIdStrings);
	}


	/**
	 * Gets the 任务接受人(String).
	 *
	 * @return the 任务接受人(String)
	 */
	public Expression getAssignListVariableName() {
		return assignListVariableName;
	}


	/**
	 * Sets the 任务接受人(String).
	 *
	 * @param assignListVariableName the new 任务接受人(String)
	 */
	public void setAssignListVariableName(Expression assignListVariableName) {
		this.assignListVariableName = assignListVariableName;
	}


	/**
	 * Gets the 1:直接主管, 2:第2级主管, 3: 第3级主管.
	 *
	 * @return the 1:直接主管, 2:第2级主管, 3: 第3级主管
	 */
	public Expression getLeaderLevel() {
		return leaderLevel;
	}


	/**
	 * Sets the 1:直接主管, 2:第2级主管, 3: 第3级主管.
	 *
	 * @param leaderLevel the new 1:直接主管, 2:第2级主管, 3: 第3级主管
	 */
	public void setLeaderLevel(Expression leaderLevel) {
		this.leaderLevel = leaderLevel;
	}


	/**
	 * Gets the 找不到主管时，由上级主管代审批.
	 *
	 * @return the 找不到主管时，由上级主管代审批
	 */
	public Expression getUseDirectorProxy() {
		return useDirectorProxy;
	}


	/**
	 * Sets the 找不到主管时，由上级主管代审批.
	 *
	 * @param useDirectorProxy the new 找不到主管时，由上级主管代审批
	 */
	public void setUseDirectorProxy(Expression useDirectorProxy) {
		this.useDirectorProxy = useDirectorProxy;
	}

	/**
	 * Gets the 节点名称.
	 *
	 * @return the 节点名称
	 */
	public Expression getNodeName() {
		return nodeName;
	}

	/**
	 * Sets the 节点名称.
	 *
	 * @param nodeName the new 节点名称
	 */
	public void setNodeName(Expression nodeName) {
		this.nodeName = nodeName;
	}
}
