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

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

import javax.inject.Named;

import org.activiti.bpmn.model.ActivitiListener;
import org.activiti.bpmn.model.BoundaryEvent;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.EndEvent;
import org.activiti.bpmn.model.EventDefinition;
import org.activiti.bpmn.model.ExclusiveGateway;
import org.activiti.bpmn.model.FieldExtension;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.IOParameter;
import org.activiti.bpmn.model.ImplementationType;
import org.activiti.bpmn.model.InclusiveGateway;
import org.activiti.bpmn.model.IntermediateCatchEvent;
import org.activiti.bpmn.model.Message;
import org.activiti.bpmn.model.MessageEventDefinition;
import org.activiti.bpmn.model.MultiInstanceLoopCharacteristics;
import org.activiti.bpmn.model.ParallelGateway;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.ScriptTask;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.ServiceTask;
import org.activiti.bpmn.model.Signal;
import org.activiti.bpmn.model.StartEvent;
import org.activiti.bpmn.model.TerminateEventDefinition;
import org.activiti.bpmn.model.UserTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.leanwo.activiti.service.base.BpmnElementService;

/**
 * BPMN 元素服务
 * 
 * @author YangZhiJie
 *
 */
@Named
public class BpmnElementServiceImpl implements BpmnElementService {

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

	@Override
	public BpmnModel createBpmnModel(String targetNamespace) {
		BpmnModel model = new BpmnModel();
		model.setTargetNamespace(targetNamespace);
		return model;
	}
	
	@Override
	public Process createProcess(String id, String name) {
		Process process = new Process();
		process.setId(id);
		process.setName(name);
		return process;
	}

	@Override
	public Message createMessage(String id, String name) {
		Message message = new Message();
		message.setId(id);
		message.setName(name);
		return message;
	}
	
	@Override
	public Signal createSignal(String id, String name, String scope) {
		Signal signal = new Signal();
		signal.setId(id);
		signal.setName(name);
		signal.setScope(scope);
		return signal;
	}
	
	@Override
	public BoundaryEvent createBoundaryEvent(String id, String name, boolean cancelActivity) {
		BoundaryEvent boundaryEvent = new BoundaryEvent();
		boundaryEvent.setId(id);
		boundaryEvent.setName(id);
		boundaryEvent.setCancelActivity(true);
		return boundaryEvent;
	}

	
	@Override
	public IOParameter createIoParameters(String source, String sourceExpression, String target,
			String targetExpression) {
		IOParameter ioParameter = new IOParameter();
		ioParameter.setSource(source);
		ioParameter.setSourceExpression(sourceExpression);
		ioParameter.setTarget(target);
		ioParameter.setTargetExpression(targetExpression);
		return ioParameter;
	}

	@Override
	public ActivitiListener createActivitiListener(String event, String implementation, String implementationType) {
		ActivitiListener activitiListener = new ActivitiListener();
		activitiListener.setEvent(event);
		activitiListener.setImplementation(implementation);
		activitiListener.setImplementationType(implementationType);
		return activitiListener;
	}

	@Override
	public List<ActivitiListener> createActivitiListeners(ActivitiListener... activitiListeners) {
		List<ActivitiListener> activitiListenerList = new ArrayList<ActivitiListener>();
		if(activitiListeners != null) {
			for(ActivitiListener activitiListener : activitiListeners) {
				activitiListenerList.add(activitiListener);
			}
		}
		return activitiListenerList;
	}

	@Override
	public UserTask createUserTask(String id, String name, String assignee) {		
		return createUserTask(id, name, assignee, false, false, null, null, null);
	}

	@Override
	public UserTask createUserTask(String id, String name, String assignee, boolean multiInstance, boolean isSequential, String multiInstanceCollection, String multiInstanceVariable, String multiInstanceCompleteCondition) {
		UserTask userTask = new UserTask();
		userTask.setId(id);
		userTask.setName(name);
		userTask.setAssignee(assignee);
		if(multiInstance) {
			//userTask.setName(name + " ${loopCounter}");
			userTask.setName(name);
			MultiInstanceLoopCharacteristics loopCharacteristics = new MultiInstanceLoopCharacteristics();
			loopCharacteristics.setSequential(isSequential);
			loopCharacteristics.setInputDataItem(multiInstanceCollection);
			loopCharacteristics.setElementVariable(multiInstanceVariable);
			loopCharacteristics.setCompletionCondition(multiInstanceCompleteCondition);
			userTask.setLoopCharacteristics(loopCharacteristics);
		}
		return userTask;
	}

	@Override
	public FieldExtension createFieldExtension(String fieldName, String fieldValue) {
		FieldExtension fieldExtension = new FieldExtension();
		fieldExtension.setFieldName(fieldName);
		fieldExtension.setStringValue(fieldValue);
		return fieldExtension;
	}

	@Override
	public List<FieldExtension> createFieldExtensions(FieldExtension... fieldExtensions) {
		List<FieldExtension> fieldExtensionList = new ArrayList<FieldExtension>();
		if(fieldExtensions != null) {
			for(FieldExtension fieldExtension : fieldExtensions) {
				fieldExtensionList.add(fieldExtension);
			}
		}
		return fieldExtensionList;
	}
	
	@Override
	public ScriptTask createScriptTask(String id, String name, String script) {
		ScriptTask scriptTask = new ScriptTask();
		scriptTask.setId(id);
		scriptTask.setName(name);
		scriptTask.setScriptFormat("groovy");
		scriptTask.setScript(script);
		return scriptTask;
	}

	
	@Override
	public SequenceFlow createSequenceFlow(String id, String name,FlowNode sourceRef, FlowNode targetRef, String conditionExpression) {
		SequenceFlow sequenceFlow = new SequenceFlow();
		sequenceFlow.setId(id);
		sequenceFlow.setSourceRef(sourceRef.getId());
		sequenceFlow.setTargetRef(targetRef.getId());
		sequenceFlow.setName(name);
		if (conditionExpression != null && conditionExpression.length() > 0) {
			sequenceFlow.setConditionExpression(conditionExpression);
		}
		return sequenceFlow;
	}

	
	@Override
	public ExclusiveGateway createExclusiveGateway(String id, String name, boolean asynchronous, boolean exclusive) {
		ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
		exclusiveGateway.setId(id);
		exclusiveGateway.setName(name);
		exclusiveGateway.setAsynchronous(asynchronous);
		exclusiveGateway.setExclusive(exclusive);
		return exclusiveGateway;
	}

	
	@Override
	public StartEvent createStartEvent(String id, String name) {
		StartEvent startEvent = new StartEvent();
		startEvent.setId(id);
		startEvent.setName(name);
		return startEvent;
	}

	
	@Override
	public EndEvent createEndEvent(String id, String name, boolean terminateAll) {
		EndEvent endEvent = new EndEvent();
		endEvent.setId(id);
		endEvent.setName(name);		
		
		if(terminateAll) {
			TerminateEventDefinition terminateEventDefinition = new TerminateEventDefinition();
			terminateEventDefinition.setTerminateAll(terminateAll);
	
			List<EventDefinition> eventDefinitions = new ArrayList<EventDefinition>();
			eventDefinitions.add(terminateEventDefinition);
			
			endEvent.setEventDefinitions(eventDefinitions);
		}
		return endEvent;
	}


	@Override
	public ParallelGateway createParallelGateway(String id, String name) {
		ParallelGateway parallelGateway = new ParallelGateway();
		parallelGateway.setId(id);
		parallelGateway.setName(name);
		return parallelGateway;
	}

	@Override
	public IntermediateCatchEvent createIntermediateCatchEvent(String id, String name) {
		IntermediateCatchEvent intermediateCatchEvent = new IntermediateCatchEvent();
		intermediateCatchEvent.setId(id);
		intermediateCatchEvent.setName(name);
		return intermediateCatchEvent;
	}

	@Override
	public MessageEventDefinition createMessageEventDefinition(String id, String messageRef) {
		MessageEventDefinition messageEventDefinition = new MessageEventDefinition();
		messageEventDefinition.setId(id);
		messageEventDefinition.setMessageRef(messageRef);
		return messageEventDefinition;
	}

	@Override
	public ServiceTask createServiceTask(String id, String name, Class delegateClass) {
		ServiceTask serviceTask = new ServiceTask();
		serviceTask.setId(id);
		serviceTask.setName(name);
		serviceTask.setImplementation(delegateClass.getName());
		serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_CLASS);
		return serviceTask;
	}

	@Override
	public InclusiveGateway createInclusiveGateway(String id, String name, boolean asynchronous, boolean exclusive) {
		InclusiveGateway inclusiveGateway = new InclusiveGateway();
		inclusiveGateway.setId(id);
		inclusiveGateway.setName(name);
		inclusiveGateway.setAsynchronous(asynchronous);
		inclusiveGateway.setExclusive(exclusive);
		return inclusiveGateway;
	}



}
