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

import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.inject.Inject;

import org.activiti.bpmn.BpmnAutoLayout;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.validation.ProcessValidator;
import org.activiti.validation.ProcessValidatorFactory;
import org.activiti.validation.ValidationError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.leanwo.activiti.dto.approver.ProcessData;
import com.leanwo.activiti.dto.approver.WorkflowDefData;
import com.leanwo.activiti.dto.base.UserSelectDefine;
import com.leanwo.activiti.service.base.ApproveEditService;
import com.leanwo.activiti.service.base.BpmnCreateBo;
import com.leanwo.activiti.service.base.BpmnElementService;
import com.leanwo.activiti.service.base.BpmnGeneratorService;
import com.leanwo.activiti.service.base.FileService;
import com.leanwo.activiti.util.FormatUtil;


/**
 * 审批编辑服务.
 *
 * @author YangZhiJie
 */
@Service
public class ApproveEditServiceImpl implements ApproveEditService {
	
	/**  */
	private static Logger logger = LoggerFactory.getLogger(ApproveEditServiceImpl.class);
	
	/**  */
	@Inject
	private ProdogServer prodogServer;
	
	/**  */
	@Inject
	private FileServer fileServer;
	
	/**  */
	@Inject
	private FileService fileService;
	
	/**  */
	@Inject
	private BpmnElementService bpmnElementService;

	/**
	 * 
	 *
	 * @param mockData 
	 * @return 
	 */
	@Override
	@Transactional
	public BpmnCreateBo createBpmnFile(WorkflowDefData mockData) {
		
		ProcessData processData = mockData.getProcessData();
	
		Boolean integrateDingDing = mockData.getAdvancedSetting().getIntegrateDingDing();
		integrateDingDing = ((integrateDingDing == null) ? false : integrateDingDing);

		Boolean triggerAfterNodeApproved = mockData.getAdvancedSetting().getTriggerAfterNodeApproved();
		triggerAfterNodeApproved = ((triggerAfterNodeApproved == null) ? false : triggerAfterNodeApproved);
		
		BpmnGeneratorService bpmnGeneratorService = new BpmnGeneratorServiceImpl(integrateDingDing, triggerAfterNodeApproved, bpmnElementService);
		
		String name = FormatUtil.formatDateTimeFormat(new Date()).replace(" ", "_").replace(":", "").replace("-", "");
		BpmnModel bpmnModel = bpmnGeneratorService.generateBpmnModel(name, processData);
		
		List<UserSelectDefine> userSelectDefineList = bpmnGeneratorService.getUserSelectDefineList();
		List<UserSelectDefine> previousAssigneeSelectDefineList = bpmnGeneratorService.getPreviousAssigneeSelectDefineList();
		
		// 2.生成BPMN自动布局
		// toggled by jack 20210305
		// 在复杂工作流的情况下，自动布局会卡主。
		BpmnAutoLayout bpmnAutoLayout = new BpmnAutoLayout(bpmnModel);
		bpmnAutoLayout.execute();

		BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
		
		byte[] convertToXML = bpmnXMLConverter.convertToXML(bpmnModel);
		String fileName = FormatUtil.formatDateTimeFormat(new Date()) + "_" + UUID.randomUUID() + ".bpmn";
		fileName = fileName.replace(" ", "_").replace(":", "_").replace("-", "_");
		
		String bpmnFileFullPath = fileServer.clientFileHome() + "\\Bpmns\\customer\\" + fileName;
		fileService.createFile(bpmnFileFullPath, convertToXML);
		
		logger.info("生成BPMN文件成功:" + bpmnFileFullPath);
		
		
		ProcessValidatorFactory processValidatorFactory=new ProcessValidatorFactory();
		ProcessValidator defaultProcessValidator = processValidatorFactory.createDefaultProcessValidator();
		
		//验证失败信息的封装ValidationError
		List<ValidationError> validates = defaultProcessValidator.validate(bpmnModel);
		if(validates != null && validates.size() > 0) {
			for(ValidationError validationError : validates) {
				logger.error("bpmn文件验证失败:" + validationError.toString());
			}
		}
		
		BpmnCreateBo bpmnCreateBo = new BpmnCreateBo();
		bpmnCreateBo.setBpmnModel(bpmnModel);
		bpmnCreateBo.setUserSelectDefineList(userSelectDefineList);
		bpmnCreateBo.setPreviousAssigneeSelectDefineList(previousAssigneeSelectDefineList);
		
		return bpmnCreateBo;
	}
	
}
