package com.leanwo.activiti.config;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.inject.Inject;
import javax.inject.Named;

import org.activiti.engine.HistoryService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.asyncexecutor.AsyncExecutor;
import org.activiti.engine.impl.asyncexecutor.multitenant.SharedExecutorServiceAsyncExecutor;
import org.activiti.engine.impl.cfg.multitenant.MultiSchemaMultiTenantProcessEngineConfiguration;
import org.activiti.engine.impl.cfg.multitenant.TenantAwareDataSource;
import org.activiti.engine.parse.BpmnParseHandler;
import org.activiti.engine.runtime.Clock;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import com.leanwo.activiti.db.DatabaseService;
import com.leanwo.activiti.service.base.DeploymentVariableMapper;
import com.leanwo.activiti.util.LoginContextUtil;

/**
 * 工作流引擎
 * 
 * @author YangZhiJie
 *
 */
@Configuration
public class WorkFlowEngineImpl {

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

//	@Inject
//	private PlatformTransactionManager transactionManager;

//	@Inject
//	private Environment environment;

	@Inject
	@Named("dataSource")
	private TenantAwareDataSource tenantawareDatasource;

	@Inject
	private DatabaseService databaseService;
	
	@Inject
	private EmailConfiguration emailConfiguration;
	

	@Bean(name = "processEngineConfiguration")
	public MultiSchemaMultiTenantProcessEngineConfiguration processEngineConfiguration(
			MyTenantInfoHolder myTenantInfoHolder,
			AsyncExecutor asyncExecutor) throws SQLException {
	    
	    // 初始化数据库
	    LoginContextUtil.setUseApplicationAccount(0L);
	    databaseService.schemaUpdate(0L);
	    
		MultiSchemaMultiTenantProcessEngineConfiguration processEngineConfiguration = new MultiSchemaMultiTenantProcessEngineConfiguration(
				myTenantInfoHolder);
		processEngineConfiguration.setDataSource(tenantawareDatasource);
//			processEngineConfiguration.setTransactionsExternallyManaged(false);
		Set<Class<?>> customMybatisMappers = new HashSet<Class<?>>();
		customMybatisMappers.add(DeploymentVariableMapper.class);
		processEngineConfiguration.setCustomMybatisMappers(customMybatisMappers);
		
		
		//String ddlAuto = environment.getProperty("spring.jpa.hibernate.ddl-auto");
		String ddlAuto = null;
		if (ddlAuto == null) {
			processEngineConfiguration
					.setDatabaseSchemaUpdate(MultiSchemaMultiTenantProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE);
		} else if ("update".equals(ddlAuto)) {
			processEngineConfiguration
					.setDatabaseSchemaUpdate(MultiSchemaMultiTenantProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
		} else if ("create-drop".equals(ddlAuto)) {
			processEngineConfiguration.setDatabaseSchemaUpdate(
					MultiSchemaMultiTenantProcessEngineConfiguration.DB_SCHEMA_UPDATE_CREATE_DROP);
		} else if ("none".equals(ddlAuto)) {
			processEngineConfiguration
					.setDatabaseSchemaUpdate(MultiSchemaMultiTenantProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE);
		}
		// processEngineConfiguration.setTransactionManager(transactionManager);
		processEngineConfiguration.setAsyncExecutorActivate(true);
		processEngineConfiguration.setAsyncExecutor(asyncExecutor);

		String emailHost = emailConfiguration.getMailServerHost();
		if (StringUtils.isNotEmpty(emailHost)) {
			processEngineConfiguration.setMailServerHost(emailHost);
			processEngineConfiguration.setMailServerPort(emailConfiguration.getMailServerPort());

			//Boolean useCredentials = emailConfiguration.getMailServerUseSSL();
			//if (Boolean.TRUE.equals(useCredentials)) {
				processEngineConfiguration.setMailServerUsername(emailConfiguration.getMailServerUsername());
				processEngineConfiguration.setMailServerPassword(emailConfiguration.getMailServerPassword());

			//}

			Boolean emailSSL = emailConfiguration.getMailServerUseSSL();
			if (emailSSL != null) {
				processEngineConfiguration.setMailServerUseSSL(emailSSL.booleanValue());
			}

			Boolean emailTLS = emailConfiguration.getMailServerUseTLS();
			if (emailTLS != null) {
				processEngineConfiguration.setMailServerUseTLS(emailTLS.booleanValue());
			}
		}

		// Limit process definition cache
		//processEngineConfiguration.setProcessDefinitionCacheLimit(
		//		environment.getProperty("activiti.process-definitions.cache.max", Integer.class, 128));
		processEngineConfiguration.setProcessDefinitionCacheLimit(128);

		// Enable safe XML. See
		// http://activiti.org/userguide/index.html#advanced.safe.bpmn.xml
		processEngineConfiguration.setEnableSafeBpmnXml(true);

		List<BpmnParseHandler> preParseHandlers = new ArrayList<BpmnParseHandler>();
		processEngineConfiguration.setPreBpmnParseHandlers(preParseHandlers);

		// processEngineConfiguration.registerTenant("dataSource0", dataSource);
		return processEngineConfiguration;
	}

	@Bean(name="processEngine")
	public ProcessEngine getProcessEngine(ProcessEngineConfiguration processEngineConfiguration) {
		return processEngineConfiguration.buildProcessEngine();
	}

	/**
	 * 获取流程存储服务组件
	 * 
	 * @return
	 */
	@Bean
	public RepositoryService getRepositoryService(ProcessEngine processEngine) {
		return processEngine.getRepositoryService();
	}

	/**
	 * 获取运行时服务组件
	 * 
	 * @return
	 */
	@Bean
	public RuntimeService getRuntimeService(ProcessEngine processEngine) {
		return processEngine.getRuntimeService();
	}

	/**
	 * 获取流程任务组件
	 * 
	 * @return
	 */
	@Bean
	public TaskService getTaskService(ProcessEngine processEngine) {
		return processEngine.getTaskService();
	}

	/**
	 * 获取历史数据服务
	 * 
	 * @return
	 */
	@Bean
	public HistoryService getHistoryService(ProcessEngine processEngine) {
		return processEngine.getHistoryService();
	}

	/**
	 * 获取管理服务
	 * 
	 * @return
	 */
	@Bean
	public ManagementService getManagementService(ProcessEngine processEngine) {
		return processEngine.getManagementService();
	}

	@Bean
	public AsyncExecutor getAsyncExecutor(MyTenantInfoHolder myTenantInfoHolder) {
		SharedExecutorServiceAsyncExecutor asyncExecutor = new SharedExecutorServiceAsyncExecutor(myTenantInfoHolder);
		asyncExecutor.setDefaultAsyncJobAcquireWaitTimeInMillis(5000);
		asyncExecutor.setDefaultTimerJobAcquireWaitTimeInMillis(5000);
		return asyncExecutor;
	}

	@Bean
	public Clock getClock(ProcessEngineConfiguration processEngineConfiguration) {
		return processEngineConfiguration.getClock();
	}
}
