/* Copyright 2012-2013 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.ced.sip.workflow.base.service;

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

import org.snaker.engine.IOrderService;
import org.snaker.engine.SnakerEngine;
import org.snaker.engine.access.Page;
import org.snaker.engine.access.QueryFilter;
import org.snaker.engine.entity.Order;
import org.snaker.engine.entity.Process;
import org.snaker.engine.entity.Surrogate;
import org.snaker.engine.entity.Task;
import org.snaker.engine.helper.StreamHelper;
import org.snaker.engine.model.TaskModel.TaskType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.ced.sip.common.WorkFlowStatus;

/**
 * @author yuqs
 * @since 0.1
 */
@Component
public class SnakerEngineFacets {
	@Autowired(required=true)
	private SnakerEngine engine;
	@Autowired(required=true)
	private  IOrderService iOrderService;
	
	public void initFlows() {
		//engine.process().deploy(StreamHelper.getStreamFromClasspath("flows/actorall.snaker"));
		//engine.process().deploy(StreamHelper.getStreamFromClasspath("flows/group.snaker"));
		//engine.process().deploy(StreamHelper.getStreamFromClasspath("flows/leave.snaker"));
		//engine.process().deploy(StreamHelper.getStreamFromClasspath("flows/forkjoin.snaker"));
		//engine.process().deploy(StreamHelper.getStreamFromClasspath("flows/custom.snaker"));
		//engine.process().deploy(StreamHelper.getStreamFromClasspath("flows/free.snaker"));
	}
	
	public SnakerEngine getEngine() {
		return engine;
	}
	
	public List<String> getAllProcessNames() {
		List<Process> list = engine.process().getProcesss(new QueryFilter());
		List<String> names = new ArrayList<String>();
		for(Process entity : list) {
			if(names.contains(entity.getName())) {
				continue;
			} else {
				names.add(entity.getName());
			}
		}
		return names;
	}
	
	public Order startInstanceById(String processId, String operator, Map<String, Object> args) {
		return engine.startInstanceById(processId, operator, args);
	}
	
	public Order startInstanceByName(String name, Integer version, String operator, Map<String, Object> args,Long comId) {
		return engine.startInstanceByName(name, version, operator, args,comId);
	}
	
	public Order startAndExecute(String name, Integer version, String operator, Map<String, Object> args,Long comId) {
		Order order = engine.startInstanceByName(name, version, operator, args,comId);
		List<Task> tasks = engine.query().getActiveTasks(new QueryFilter().setOrderId(order.getId()));
		List<Task> newTasks = new ArrayList<Task>();
		if(tasks != null && tasks.size() > 0) {
			Task task = tasks.get(0);
			newTasks.addAll(engine.executeTask(task.getId(), operator, args));
		}
		return order;
	}
	
	public Order startAndExecute(String processId, String operator, Map<String, Object> args) {
		Order order = engine.startInstanceById(processId, operator, args);
		List<Task> tasks = engine.query().getActiveTasks(new QueryFilter().setOrderId(order.getId()));
		List<Task> newTasks = new ArrayList<Task>();
		if(tasks != null && tasks.size() > 0) {
			Task task = tasks.get(0);
			newTasks.addAll(engine.executeTask(task.getId(), operator, args));
		}
		return order;
	}
	public List<Task> execute(String taskId, String operator, Map<String, Object> args) {
		List<Task> list=engine.executeTask(taskId, operator, args);
		return list;
	}
	/**
	 * 退回重新发起的流程处理
	 * @param taskId
	 * @param ord
	 * @param operator
	 * @param args
	 * @return
	 */
	public List<Task> executeBackToInit(String taskId, String operator, Map<String, Object> args) {
		Task task = engine.query().getTask(taskId);
		List<Task> list=engine.executeTask(taskId, operator, args);
		//lgl重新修改的源码 作用是当申请人提交申请时候更新historyOrder表中的OrderState为1
		engine.executeHistoryOrder(task.getOrderId(),Integer.parseInt(WorkFlowStatus.WORK_FLOW_ORDER_STATUS_1));
		return list;
	}
	/**
	 * 自主退回后，改变审批流程了
	 * @param OrderId
	 * @param taskId
	 * @param operator
	 * @param args
	 * @return
	 */
	public List<Task> executeBackToInit2(String taskId, String operator, Map<String, Object> args) {
		Task task = engine.query().getTask(taskId);
		List<Task> list=engine.executeTask(taskId, operator, args);
		//lgl重新修改的源码 作用是当申请人提交申请时候更新historyOrder表中的OrderState为1
		engine.executeHistoryOrderAndOrder(task.getOrderId(), Integer.parseInt(WorkFlowStatus.WORK_FLOW_ORDER_STATUS_1), args);
		
		return list;
	}
	public List<Task> executeAndJumpReback(String taskId,String orerId, String operator, Map<String, Object> args, String nodeName) {
		List<Task> list=engine.executeAndJumpTaskReback(taskId, operator, args, nodeName);
		//lgl重新修改的源码 作用是更新historyOrder表中的OrderState为3
		engine.executeHistoryOrder(orerId,Integer.parseInt(WorkFlowStatus.WORK_FLOW_ORDER_STATUS_3));
		return list;
	}
	
	public List<Task> transfer(String taskId, String operator, String... actors) {
		List<Task> tasks = engine.task().createNewTask(taskId, TaskType.Major.ordinal(), actors);
		engine.task().complete(taskId, operator);
		return tasks;
	}
	
	public void addSurrogate(Surrogate entity) {
		if(entity.getState() == null) {
			entity.setState(1);
		}
		engine.manager().saveOrUpdate(entity);
	}
	
	public void deleteSurrogate(String id) {
		engine.manager().deleteSurrogate(id);
	}
	
	public Surrogate getSurrogate(String id) {
		return engine.manager().getSurrogate(id);
	}
	
	public List<Surrogate> searchSurrogate(Page<Surrogate> page, QueryFilter filter) {
		return engine.manager().getSurrogate(page, filter);
	}

	public IOrderService getiOrderService() {
		return iOrderService;
	}

	public void setiOrderService(IOrderService iOrderService) {
		this.iOrderService = iOrderService;
	}

	public void setEngine(SnakerEngine engine) {
		this.engine = engine;
	}

}
