package com.apobates.forum.trident;

import java.io.IOException;
import javax.persistence.EntityManagerFactory;
import javax.servlet.Filter;
import javax.sql.DataSource;
import com.apobates.forum.utils.Commons;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.jcache.JCacheCacheManager;
import org.springframework.cache.jcache.JCacheManagerFactoryBean;
import org.springframework.context.annotation.*;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.alibaba.druid.pool.DruidDataSource;
import com.apobates.forum.core.impl.CoreAppConfig;
import com.apobates.forum.core.impl.CoreModuleActionEventAspect;
import com.apobates.forum.letterbox.impl.LetterAppConfig;
import com.apobates.forum.member.impl.MemberActionAspect;
import com.apobates.forum.member.impl.MemberAppConfig;
/**
 * Spring framework配置类
 * @applicationContext.xml
 * 
 * @author xiaofanku
 * @since 20200302
 */
@Configuration
@PropertySource("classpath:global.properties")
@EnableLoadTimeWeaving
@EnableAspectJAutoProxy(proxyTargetClass=true)
@EnableTransactionManagement(proxyTargetClass=true)
@Import(value={MemberAppConfig.class, CoreAppConfig.class, LetterAppConfig.class})
@ComponentScan(basePackages = {"com.apobates.forum.trident.event"}, useDefaultFilters = false, includeFilters = {@ComponentScan.Filter(classes = {org.springframework.stereotype.Component.class})})
public class TridentAppConfig{
	@Autowired
	private Environment env;
	//
	@Bean
	public JdbcProperties getJdbcProperties(){
		JdbcProperties jp = new JdbcProperties();
		jp.setDriverClassName(env.getProperty("jdbc.driverClassName"));
		jp.setUrl(env.getProperty("jdbc.url"));
		jp.setUsername(env.getProperty("jdbc.username"));
		jp.setPassword(env.getProperty("jdbc.password"));
		jp.setPoolInit(Commons.stringToInteger(()->env.getProperty("jdbc.pool.init"), 1));
		jp.setPoolMinIdle(Commons.stringToInteger(()->env.getProperty("jdbc.pool.minIdle"), 3));
		jp.setPoolMaxActive(Commons.stringToInteger(()->env.getProperty("jdbc.pool.maxActive"), 20));
		jp.setPoolTestSql(env.getProperty("jdbc.pool.testSql"));
		jp.setJpaUnitName(env.getProperty("jpa.unit-name"));
		return jp;
	}
	// 数据源
	@Bean(value = "dataSource", initMethod = "init", destroyMethod = "close") // 假如没有指定名字，默认为方法名
	public DataSource buildDataSource(JdbcProperties jdbcProperties) {
		DruidDataSource ds = new DruidDataSource();
		ds.setDriverClassName(jdbcProperties.getDriverClassName());
		ds.setUrl(jdbcProperties.getUrl());
		ds.setUsername(jdbcProperties.getUsername());
		ds.setPassword(jdbcProperties.getPassword());
		ds.setInitialSize(jdbcProperties.getPoolInit());
		ds.setMinIdle(jdbcProperties.getPoolMinIdle());
		ds.setMaxActive(jdbcProperties.getPoolMaxActive());
		ds.setMaxWait(60000);
		ds.setTimeBetweenEvictionRunsMillis(60000);
		ds.setMinEvictableIdleTimeMillis(300000);
		ds.setValidationQuery(jdbcProperties.getPoolTestSql());
		ds.setTestWhileIdle(true);
		ds.setTestOnBorrow(false);
		ds.setTestOnReturn(false);
		return ds;
	}
	//ADD PERSISTENCE SUPPORT HERE (jpa, hibernate, etc)
	@Bean
	public JpaVendorAdapter getJpaVendorAdapter(){
		EclipseLinkJpaVendorAdapter elva = new org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter();
		elva.setGenerateDdl(true);
		elva.setShowSql(true);
		elva.setDatabase(Database.MYSQL);
		elva.setDatabasePlatform("org.eclipse.persistence.platform.database.MySQLPlatform");
		return elva;
	}
	@Bean
	public LocalContainerEntityManagerFactoryBean entityManagerFactory(JdbcProperties jdbcProperties, DataSource dataSource, JpaVendorAdapter jpaVendorAdapter){
		LocalContainerEntityManagerFactoryBean aemf = new org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean();
		aemf.setPersistenceUnitName(jdbcProperties.getJpaUnitName());
		aemf.setDataSource(dataSource);
		aemf.setPersistenceXmlLocation("classpath:META-INF/persistence.xml");
		aemf.setJpaVendorAdapter(jpaVendorAdapter);
		aemf.setJpaDialect(new org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect());
		return aemf;
	}
	@Bean
	public JpaTransactionManager transactionManager(EntityManagerFactory emf) {
		JpaTransactionManager jtm = new org.springframework.orm.jpa.JpaTransactionManager();
		jtm.setEntityManagerFactory(emf);
		return jtm;
	}
	//缓存|Ehcache 3.x is fully JSR-107 compliant and no dedicated support is required for it
	@Bean("cacheManagerFactory")
	public JCacheManagerFactoryBean cacheManagerFactory() throws IOException {
		JCacheManagerFactoryBean jCacheManagerFactoryBean = new org.springframework.cache.jcache.JCacheManagerFactoryBean();
		jCacheManagerFactoryBean.setCacheManagerUri(new ClassPathResource("ehcache.xml").getURI());
		return jCacheManagerFactoryBean;
	}
	@Bean("cacheManager")
	public JCacheCacheManager cacheManager(@Qualifier("cacheManagerFactory") JCacheManagerFactoryBean cacheManagerFactory) throws IOException {
		JCacheCacheManager jCacheCacheManager = new org.springframework.cache.jcache.JCacheCacheManager();
		jCacheCacheManager.setCacheManager(cacheManagerFactory.getObject());
		jCacheCacheManager.setTransactionAware(true);
		return jCacheCacheManager;
	}
	//功能模块的拦截器 
	@Bean
	public MemberActionAspect buildMa(){
		return new com.apobates.forum.member.impl.MemberActionAspect();
	}
	@Bean
	public CoreModuleActionEventAspect buildCmae(){
		return new com.apobates.forum.core.impl.CoreModuleActionEventAspect();
	}
	@Bean("tokenParamFilter")
	public Filter requestTokenParameterFilter(){
		return new com.apobates.forum.trident.controller.helper.RequestTokenParameterFilter();
	}
}
