package sgc.portal.base;

import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.ubireport.server.UbiServer4;

import sgc.portal.SgcPortalProperties;
import sgc.portal.base.format.DateJsonDeserializer;
import sgc.portal.base.format.DateJsonSerializer;
import sgc.portal.base.format.DateTimeJsonDeserializer;
import sgc.portal.base.format.DateTimeJsonSerializer;
import sgc.portal.com.sym.user.UserDetailsMethodArgumentResolver;
import sgc.portal.security.SecurityDecisionMaker;
import sgc.portal.security.SessionObserver;
import sgc.portal.security.model.BearerTokenWrapper;
import websquare.http.DefaultRequestDispatcher;

/**
 * <pre>
 * Spring framework을 확장하면 확장 point를 Spring framework에 등록해야한다.
 * 해당 클래스는 Spring이 제공하는 WebMvcConfigurerAdapter를 상속하여
 * KRIIS 시스템에서 확장한 내용들을 등록하는 역할을한다.
 * </pre>
 *
 * @author YongSang
 */
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
    @Autowired
    private SgcPortalProperties props;

    /**
     * Spring interceptor를 등록.
     * 로그인 사용자를 구분하기위한 인터셉터들이 등록된다.
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SecurityDecisionMaker());
        registry.addInterceptor(new SessionObserver())
                .excludePathPatterns("/batch/**")
                .excludePathPatterns("/error");
        //registry.addInterceptor(new SecurityRefererPolicy());
        //registry.addInterceptor(new CsrfPreventer());
    }
    
    @Bean
    @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public BearerTokenWrapper bearerTokenWrapper() {
      return new BearerTokenWrapper();
    }
    
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        //  개발에서 사용할 때는 Proxy 를 이용하기 때문에 Origins 에 로컬서버를 추개해 주어야 함.
        registry.addMapping("/mobile/api/**")
        		//.allowedOrigins("http://localhost:8100","http://localhost:8101","http://192.168.36.22:8100","http://192.168.0.55:8100","http://192.168.36.37:8100")
        		.allowedOrigins("http://localhost:8100","http://localhost:8101","http://192.168.0.55:8100")
                .allowedMethods("GET,HEAD,POST,PUT,DELETE,TRACE,OPTIONS,PATCH".split(","))
                .allowedHeaders("*")
            	.allowCredentials(true)
                .maxAge(3000);
    }

    /**
     * 로그인사용자의 세션 값을 간편하게 가져오기 위해 HandlerMethodArgumentResolver를 등록
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new UserDetailsMethodArgumentResolver());
    }

    /**
     * web.xml의 welcome file을 대체
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("forward:/index.html");
    }

    /**
     * 웹스퀘어를 등록.
     *
     * @return the servlet registration bean
     */
    @Bean
    public ServletRegistrationBean<DefaultRequestDispatcher> webSequareRequestDispatcher() {
        ServletRegistrationBean<DefaultRequestDispatcher> webSequareRequestDispatcher =
                new ServletRegistrationBean<DefaultRequestDispatcher>(new DefaultRequestDispatcher(), "*.wq");
        Map<String, String> initParameters = new HashMap<>();
        initParameters.put("WEBSQUARE_HOME", props.getWebSquare().getHomeLocation());
        webSequareRequestDispatcher.setInitParameters(initParameters);
        return webSequareRequestDispatcher;
    }

//    private static final String dateFormat = "yyyyMMdd";
//    private static final String dateTimeFormat = "yyyyMMddHHmmss";

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyyMMddHHmmss");

        return builder -> {
//            builder.simpleDateFormat(dateTimeFormat);
            builder.serializers(new DateJsonSerializer(dateFormat));
            builder.serializers(new DateTimeJsonSerializer(dateTimeFormat));
            builder.deserializers(new DateJsonDeserializer(dateFormat));
            builder.deserializers(new DateTimeJsonDeserializer(dateTimeFormat));
        };
    }
    
	/**
     * UbiServer4등록.
     *
     * @return the servlet registration bean
     */
    @Bean
    public ServletRegistrationBean<UbiServer4> getServletRegiatrationBean() {
        ServletRegistrationBean<UbiServer4> registrationBean = new ServletRegistrationBean<UbiServer4>(new UbiServer4());
        registrationBean.addUrlMappings("/UbiServer");
        return registrationBean;
    }
}