package com.blueland.bpm.manage.web;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.CallActivity;
import org.activiti.bpmn.model.ExpandProperty;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.GraphicInfo;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.Task;
import org.activiti.bpmn.model.UserTask;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.blueland.bpm.engine.config.service.ActivityInfoConfigManager;
import com.blueland.bpm.engine.core.service.ProcessDefinitionService;
import com.blueland.bpm.engine.core.service.ProcessModelService;
import com.blueland.bpm.engine.util.ProcessModelUtils;
import com.blueland.bpm.manage.util.ComparatorTransition;

@Controller
@RequestMapping(value = "/actInfo/sequenceFlow")
public class SequenceFlowController extends BaseProcessController{
	@Autowired
	private ProcessDefinitionService processDefinitionService;
	@Autowired
	private ProcessModelService processModelService;
	@Autowired
	private ActivityInfoConfigManager activityInfoConfigManager;

	
	
	@RequestMapping(value = "list")
	public ModelAndView list(String procDefId,String actId) {
		ModelAndView modelAndView = new ModelAndView(
				"/actInfo/sequenceFlow/list");
		BpmnModel bpmnModel=processModelService.getBpmnModelByProcDefId(procDefId);
		FlowElement flowElement=bpmnModel.getFlowElement(actId);
		Task task =null;
		CallActivity callActivity =null;
		List<SequenceFlow> sequenceFlows=null;
		if(flowElement instanceof Task){
			 task = (Task)bpmnModel.getFlowElement(actId);
			 sequenceFlows=task.getOutgoingFlows();
		}else if(flowElement instanceof CallActivity){
			callActivity = (CallActivity)bpmnModel.getFlowElement(actId);
			sequenceFlows=callActivity.getOutgoingFlows();
		}
		Collections.sort(sequenceFlows,new ComparatorTransition());
		for (SequenceFlow sequenceFlow : sequenceFlows) {
			sequenceFlow.setSourceRefName(bpmnModel.getFlowElement(sequenceFlow.getSourceRef()).getName());
			sequenceFlow.setTargetRefName(bpmnModel.getFlowElement(sequenceFlow.getTargetRef()).getName());
		}
		modelAndView.addObject("userTask", task instanceof UserTask?(UserTask)task:flowElement);
		modelAndView.addObject("procDefId", procDefId);
		return modelAndView;
	}
	
	@RequestMapping(value = "edit")
	public ModelAndView editSequenceFlow(String procDefId,String sequenceFlowId) {
		ModelAndView modelAndView = new ModelAndView(
				"/actInfo/sequenceFlow/edit");
		BpmnModel bpmnModel=processModelService.getBpmnModelByProcDefId(procDefId);
		SequenceFlow sequenceFlow=(SequenceFlow) bpmnModel.getFlowElement(sequenceFlowId);
		initExpandProperties(sequenceFlow);
		ProcessModelUtils.filterExpandProperties(sequenceFlow);
		modelAndView.addObject("sequenceFlow", sequenceFlow);
		ExpandProperty nextActAliasEx=ProcessModelUtils.findExpandProperties(sequenceFlow.getExpandProperties(), "TRANSITION_NEXTACT_ALIAS");
		if(nextActAliasEx!=null) {
			modelAndView.addObject("nextActAlias", nextActAliasEx.getValue());
		}
		modelAndView.addObject("procDefId", procDefId);
		modelAndView.addObject("activitys", processDefinitionService.getProcessUserActivitys(procDefId));
		return modelAndView;
	}
	
	@RequestMapping(value = "update")
	@ResponseBody
	public String updateSequenceFlow(String procDefId,SequenceFlow params,String nextActAlias) {
		BpmnModel bpmnModel=processModelService.getBpmnModelByProcDefId(procDefId);
		SequenceFlow sequenceFlow=(SequenceFlow) bpmnModel.getFlowElement(params.getId());
		sequenceFlow.setACTIVITY_USER_SAME_ORG_LEVEL(params.getACTIVITY_USER_SAME_ORG_LEVEL());
		sequenceFlow.setTRANSITION_DISPLAY_ORDER(params.getTRANSITION_DISPLAY_ORDER());
		sequenceFlow.setTRANSITION_RETURN_FORMER(params.getTRANSITION_RETURN_FORMER());
		sequenceFlow.setName(params.getName());
		sequenceFlow.setConditionExpression(params.getConditionExpression());
		ProcessModelUtils.addExpandProperties(sequenceFlow,"ACTIVITY_USER_SAME_ORG_LEVEL",sequenceFlow.getACTIVITY_USER_SAME_ORG_LEVEL(),"ACTIVITY_USER_SAME_ORG_LEVEL");
		ProcessModelUtils.addExpandProperties(sequenceFlow,"TRANSITION_DISPLAY_ORDER",sequenceFlow.getTRANSITION_DISPLAY_ORDER(),"TRANSITION_DISPLAY_ORDER");
		ProcessModelUtils.addExpandProperties(sequenceFlow,"TRANSITION_RETURN_FORMER",sequenceFlow.getTRANSITION_RETURN_FORMER(),"TRANSITION_RETURN_FORMER");
		ProcessModelUtils.addExpandProperties(sequenceFlow,"TRANSITION_NEXTACT_ALIAS",nextActAlias,"TRANSITION_NEXTACT_ALIAS");
		
		boolean isUpdateProcessImage=false;
		if(params.getName()==null&&sequenceFlow.getName()!=null){
			isUpdateProcessImage=true;
		}else if(sequenceFlow.getName()==null||params.getName()!=null){
			isUpdateProcessImage=true;
		}else if(!sequenceFlow.getName().equals(params.getName())){
			isUpdateProcessImage=true;
		}
		GraphicInfo graphicInfo=new GraphicInfo();
		graphicInfo.setX(0.0);
		graphicInfo.setY(0.0);
		graphicInfo.setHeight(0.0);
		graphicInfo.setWidth(0.0);
		bpmnModel.addLabelGraphicInfo(sequenceFlow.getId(), graphicInfo);
		boolean result=updateBpmnModel(bpmnModel,procDefId,isUpdateProcessImage);
		return result?this.ACTION_SUCCESS:this.ACTION_ERROR;
	}
	
	@RequestMapping(value = "createProperty")
	public ModelAndView createProperty(String procDefId,String sequenceFlowId) {
		ModelAndView modelAndView = new ModelAndView(
				"/actInfo/sequenceFlow/property/create");
		BpmnModel bpmnModel=processModelService.getBpmnModelByProcDefId(procDefId);
		SequenceFlow sequenceFlow=(SequenceFlow) bpmnModel.getFlowElement(sequenceFlowId);
		modelAndView.addObject("sequenceFlow", sequenceFlow);
		modelAndView.addObject("procDefId", procDefId);
		return modelAndView;
	}
	@RequestMapping(value = "saveProperty")
	@ResponseBody
	public String saveProperty(String procDefId,String sequenceFlowId,ExpandProperty expandProperty) {
		BpmnModel bpmnModel=processModelService.getBpmnModelByProcDefId(procDefId);
		SequenceFlow sequenceFlow=(SequenceFlow) bpmnModel.getFlowElement(sequenceFlowId);
		List<ExpandProperty> expandPropertys= sequenceFlow.getExpandProperties();
		expandPropertys.add(expandProperty);
		boolean result=updateBpmnModel(bpmnModel,procDefId,false);
		return result?this.ACTION_SUCCESS:this.ACTION_ERROR;
	}
	
	@RequestMapping(value = "editProperty")
	public ModelAndView editProperty(String procDefId,String sequenceFlowId,String expandPropertyId) {
		ModelAndView modelAndView = new ModelAndView(
				"/actInfo/sequenceFlow/property/edit");
		BpmnModel bpmnModel=processModelService.getBpmnModelByProcDefId(procDefId);
		SequenceFlow sequenceFlow=(SequenceFlow) bpmnModel.getFlowElement(sequenceFlowId);
		ExpandProperty editExpandProperty=ProcessModelUtils.findExpandProperties(sequenceFlow.getExpandProperties(),expandPropertyId);
		modelAndView.addObject("sequenceFlow", sequenceFlow);
		modelAndView.addObject("expandProperty", editExpandProperty);
		modelAndView.addObject("procDefId", procDefId);
		return modelAndView;
	}
	
	@RequestMapping(value = "updateProperty")
	@ResponseBody
	public String updateProperty(String procDefId,String sequenceFlowId,ExpandProperty expandProperty) {
		BpmnModel bpmnModel=processModelService.getBpmnModelByProcDefId(procDefId);
		SequenceFlow sequenceFlow=(SequenceFlow) bpmnModel.getFlowElement(sequenceFlowId);
		ProcessModelUtils.removeExpandProperties(sequenceFlow.getExpandProperties(),expandProperty.getId());
		sequenceFlow.getExpandProperties().add(expandProperty);
		boolean result=updateBpmnModel(bpmnModel,procDefId,false);
		return result?this.ACTION_SUCCESS:this.ACTION_ERROR;
	}
	
	@RequestMapping(value = "deleteProperty")
	@ResponseBody
	public String deleteProperty(String procDefId,String id,String[] expandPropertyIds) {
		BpmnModel bpmnModel=processModelService.getBpmnModelByProcDefId(procDefId);
		SequenceFlow sequenceFlow=(SequenceFlow) bpmnModel.getFlowElement(id);
		for (String expandPropertyId : expandPropertyIds) {
			ProcessModelUtils.removeExpandProperties(sequenceFlow.getExpandProperties(),expandPropertyId);
		}
		boolean result=updateBpmnModel(bpmnModel,procDefId,false);
		return result?this.ACTION_SUCCESS:this.ACTION_ERROR;
	}
	/**
	 * 查看输出线描述
	 * @param procDefId
	 * @param sequenceFlowId
	 * @return
	 */
	@RequestMapping(value = "viewDescription")
	@ResponseBody
	public Map<String,Object> viewDescription(String procDefId,String sequenceFlowId) {
		Map<String,Object> result = new HashMap<String,Object>();
		BpmnModel bpmnModel=processModelService.getBpmnModelByProcDefId(procDefId);
		SequenceFlow sequenceFlow=(SequenceFlow) bpmnModel.getFlowElement(sequenceFlowId);
		initExpandProperties(sequenceFlow);
		ProcessModelUtils.filterExpandProperties(sequenceFlow);
		result.put("sequenceFlow", sequenceFlow);
		return result;
	}
	
	
	public static  void initExpandProperties(SequenceFlow sequenceFlow){
		ExpandProperty ACTIVITY_USER_SAME_ORG_LEVEL=ProcessModelUtils.findExpandProperties(sequenceFlow.getExpandProperties(), "ACTIVITY_USER_SAME_ORG_LEVEL");
		ExpandProperty TRANSITION_DISPLAY_ORDER=ProcessModelUtils.findExpandProperties(sequenceFlow.getExpandProperties(), "TRANSITION_DISPLAY_ORDER");
		ExpandProperty TRANSITION_RETURN_FORMER=ProcessModelUtils.findExpandProperties(sequenceFlow.getExpandProperties(), "TRANSITION_RETURN_FORMER");
		if(ACTIVITY_USER_SAME_ORG_LEVEL!=null&&StringUtils.isNotEmpty(ACTIVITY_USER_SAME_ORG_LEVEL.getValue())){
			sequenceFlow.setACTIVITY_USER_SAME_ORG_LEVEL(ACTIVITY_USER_SAME_ORG_LEVEL.getValue());
		}
		if(TRANSITION_DISPLAY_ORDER!=null&&StringUtils.isNotEmpty(TRANSITION_DISPLAY_ORDER.getValue())){
			sequenceFlow.setTRANSITION_DISPLAY_ORDER(TRANSITION_DISPLAY_ORDER.getValue());
		}
		if(TRANSITION_RETURN_FORMER!=null&&StringUtils.isNotEmpty(TRANSITION_RETURN_FORMER.getValue())){
			sequenceFlow.setTRANSITION_RETURN_FORMER(TRANSITION_RETURN_FORMER.getValue());
		}
	}
	
}
