package incheon.com.config;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.context.annotation.Primary;

import incheon.com.cmm.EgovComTraceHandler;
import incheon.com.cmm.ImagePaginationRenderer;
import incheon.com.cmm.AdminPaginationRenderer;
import incheon.com.cmm.DefaultPaginationRenderer;
import incheon.com.cmm.web.EgovMultipartResolver;

import org.egovframe.rte.fdl.cmmn.trace.LeaveaTrace;
import org.egovframe.rte.fdl.cmmn.trace.handler.TraceHandler;
import org.egovframe.rte.fdl.cmmn.trace.manager.DefaultTraceHandleManager;
import org.egovframe.rte.fdl.cmmn.trace.manager.TraceHandlerService;
import org.egovframe.rte.fdl.cryptography.EgovPasswordEncoder;
import org.egovframe.rte.fdl.cryptography.impl.EgovARIACryptoServiceImpl;
import org.egovframe.rte.ptl.mvc.tags.ui.pagination.DefaultPaginationManager;
import org.egovframe.rte.ptl.mvc.tags.ui.pagination.PaginationRenderer;

/**
 * @ClassName : EgovConfigAppCommon.java
 * @Description : 공통 Bean 설정
 *
 * @author : 윤주호
 * @since  : 2021. 7. 20
 * @version : 1.0
 *
 * <pre>
 * << 개정이력(Modification Information) >>
 *
 *   수정일              수정자               수정내용
 *  -------------  ------------   ---------------------
 *   2021. 7. 20    윤주호               최초 생성
 *   2023. 5. 05    crlee              remove EgovMessageSource config
 * </pre>
 *
 */
@Configuration
@ComponentScan(basePackages = "incheon", includeFilters = {
	@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Service.class),
	@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Repository.class)
}, excludeFilters = {
	@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class),
	@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class)
})
public class EgovConfigAppCommon {

	// 파일 업로드 설정
	@Value("${Globals.fileUpload.maxUploadSize:100000000}")
	private long maxUploadSize;

	@Value("${Globals.fileUpload.maxInMemorySize:100000000}")
	private long maxInMemorySize;

	@Value("${Globals.fileUpload.maxFileCount:200}")
	private int maxFileCount;

	// 암호화 설정
	@Value("${Globals.crypto.passwordEncoder.algorithm:SHA-256}")
	private String passwordEncoderAlgorithm;

	@Value("${Globals.crypto.passwordEncoder.hashedPassword:gdyYs/IZqY86VcWhT8emCYfqY1ahw2vtLG+/FzNqtrQ=}")
	private String hashedPassword;

	@Value("${Globals.crypto.aria.blockSize:1024}")
	private int ariaBlockSize;

	/**
	 * @return AntPathMatcher 등록.  Ant 경로 패턴 경로와 일치하는지 여부를 확인
	 */
	@Bean
	public AntPathMatcher antPathMatcher() {
		return new AntPathMatcher();
	}


	/**
	 * @return [LeaveaTrace 설정] defaultTraceHandler 등록
	 */
	@Bean
	public EgovComTraceHandler defaultTraceHandler() {
		return new EgovComTraceHandler();
	}

	/**
	 * @return [LeaveaTrace 설정] traceHandlerService 등록. TraceHandler 설정
	 */
	@Bean
	public DefaultTraceHandleManager traceHandlerService() {
		DefaultTraceHandleManager defaultTraceHandleManager = new DefaultTraceHandleManager();
		defaultTraceHandleManager.setReqExpMatcher(antPathMatcher());
		defaultTraceHandleManager.setPatterns(new String[] {"*"});
		defaultTraceHandleManager.setHandlers(new TraceHandler[] {defaultTraceHandler()});
		return defaultTraceHandleManager;
	}

	/**
	 * @return [LeaveaTrace 설정] LeaveaTrace 등록
	 */
	@Bean
	public LeaveaTrace leaveaTrace() {
		LeaveaTrace leaveaTrace = new LeaveaTrace();
		leaveaTrace.setTraceHandlerServices(new TraceHandlerService[] {traceHandlerService()});
		return leaveaTrace;
	}

	/**
	 * @return [ImagePaginationRenderer 설정] ImagePaginationRenderer 등록
	 */
	@Bean
	public ImagePaginationRenderer imageRenderer() {
		return new ImagePaginationRenderer();
	}

	/**
	 * @return [AdminPaginationRenderer 설정] AdminPaginationRenderer 등록
	 */
	@Bean
	public AdminPaginationRenderer adminRenderer() {
		return new AdminPaginationRenderer();
	}

	/**
	 * @return [DefaultPaginationRenderer 설정] DefaultPaginationRenderer 등록 (KRDS 디자인)
	 */
	@Bean
	public DefaultPaginationRenderer defaultRenderer() {
		return new DefaultPaginationRenderer();
	}

	/**
	 * @return [PaginationRenderer 설정] defaultPaginationManager 설정.
	 */
	@Bean
	public DefaultPaginationManager paginationManager() {
		DefaultPaginationManager defaultPaginationManager = new DefaultPaginationManager();

		Map<String, PaginationRenderer> rendererType = new HashMap<>();
		rendererType.put("image", imageRenderer());
		rendererType.put("admin", adminRenderer());
		rendererType.put("default", defaultRenderer());
		defaultPaginationManager.setRendererType(rendererType);
		
		return defaultPaginationManager;
	}

	/**
	 * 확장자 제한 : globals.properties > Globals.fileUpload.Extensions로 설정
	 * @return [MultipartResolver 설정] EgovMultipartResolver 등록
	 * MultipartFilter가 사용할 MultipartResolver 설정
	 */
	@Bean
	@Primary
	public MultipartResolver multipartResolver() {
		EgovMultipartResolver egovMultipartResolver = new EgovMultipartResolver();
		egovMultipartResolver.setMaxUploadSize(maxUploadSize);
		egovMultipartResolver.setMaxInMemorySize((int)maxInMemorySize);
		egovMultipartResolver.setMaxUploadSizePerFile(maxUploadSize / maxFileCount); // 개별 파일 크기 제한
		egovMultipartResolver.setSupportedMethods("POST","PUT");
		return egovMultipartResolver;
	}
	
	/**
	 * 암복호화
	 * @return [EgovPasswordEncoder 설정] EgovPasswordEncoder 등록
	 */
	@Bean
	public EgovPasswordEncoder egovPasswordEncoder() {
		EgovPasswordEncoder egovPasswordEncoder = new EgovPasswordEncoder();
		egovPasswordEncoder.setAlgorithm(passwordEncoderAlgorithm);
		egovPasswordEncoder.setHashedPassword(hashedPassword);
		return egovPasswordEncoder;
	}
	
	/**
	 * 암복호화
	 * @return [EgovARIACryptoServiceImpl 설정] EgovARIACryptoServiceImpl 등록
	 */
	@Bean
	public EgovARIACryptoServiceImpl egovARIACryptoService() {
		EgovARIACryptoServiceImpl egovARIACryptoServiceImpl = new EgovARIACryptoServiceImpl();
		egovARIACryptoServiceImpl.setPasswordEncoder(egovPasswordEncoder());
		egovARIACryptoServiceImpl.setBlockSize(ariaBlockSize);
		return egovARIACryptoServiceImpl;
	}
}
