package com.apobates.forum.thrones.admin;

import com.apobates.forum.attention.ImageStoreDomain;
import com.apobates.forum.core.ImageIOMeta;
import com.apobates.forum.member.storage.OnlineMemberStorage;
import com.apobates.forum.member.storage.cookie.CookieMetaConfig;
import com.apobates.forum.thrones.admin.controller.helper.AdminIdentityInterceptor;
import com.apobates.forum.thrones.admin.controller.helper.FormTokenParameterInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.http.MediaType;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.BeanNameViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

/**
 * 后端Spring MVC配置类
 * @author xiaofanku
 * @see 20200603
 */
@Configuration
@PropertySource(value = "classpath:global.properties", ignoreResourceNotFound = true, encoding = "UTF-8")
@EnableWebMvc
@ComponentScan(basePackages = {"com.apobates.forum.thrones.admin.controller"}, useDefaultFilters = false, includeFilters = {@ComponentScan.Filter(classes = {org.springframework.stereotype.Controller.class}),@ComponentScan.Filter(classes = {org.springframework.stereotype.Component.class})})
public class ThronesAdminFrontConfig implements WebMvcConfigurer{
    @Value("${site.domain}")
    private String siteDomain;
    @Value("${web.view.index}")
    private String defPath;
    @Value("${site.cookieSymbol}")
    private String cookieName;
    @Value("${site.cookieDomain}")
    private String cookieDomain;
    @Value("${site.cookiePath}")
    private String cookiePath;
    @Value("${img.bucket.domain}")
    private String imageBucketDomain;
    @Value("${img.bucket.upload.direct}")
    private String imageBucketUploadDirect;
    /**
     * 配置请求视图映射
     *
     * @return
     */
    @Bean
    public InternalResourceViewResolver resourceViewResolver() {
        InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
        //请求视图文件的前缀地址
        internalResourceViewResolver.setPrefix("/WEB-INF/layout/page/");
        //请求视图文件的后缀
        internalResourceViewResolver.setSuffix(".jsp");
        internalResourceViewResolver.setViewClass(JstlView.class);
        return internalResourceViewResolver;
    }
    @Bean
    public AdminIdentityInterceptor getAdminIdenInter() {
        return new com.apobates.forum.thrones.admin.controller.helper.AdminIdentityInterceptor();
    }
    @Bean
    public FormTokenParameterInterceptor getFormTokenInter(){
        return new com.apobates.forum.thrones.admin.controller.helper.FormTokenParameterInterceptor();
    }
    //静态资源映射
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("/static/").setCachePeriod(31536000);
    }
    
    //定义无Controller的path<->view直接映射
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("redirect:"+defPath);
    }
    //定义视图文件解析View resolvers
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        BeanNameViewResolver beanResolver = new BeanNameViewResolver();
        beanResolver.setOrder(1);
        registry.viewResolver(beanResolver);
        registry.viewResolver(resourceViewResolver());
    }
    //对静态资源文件的访问， 将无法mapping到Controller的path交给default servlet handler处理 
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
    //注册媒体类型
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.ignoreAcceptHeader(false)
                .favorPathExtension(true)
                .mediaType("json", MediaType.APPLICATION_JSON)
                .mediaType("xml", MediaType.APPLICATION_XML)
                .mediaType("rss", MediaType.APPLICATION_RSS_XML);
    }
    //拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //管理员访问的地址
        registry.addInterceptor(getAdminIdenInter()).excludePathPatterns("/").excludePathPatterns("/static/**").addPathPatterns("/**");
        //表单的token设置
        registry.addInterceptor(getFormTokenInter()).excludePathPatterns("/static/**").addPathPatterns("/**");
    }
    //HV && BV
    @Override
    public Validator getValidator() {
        LocalValidatorFactoryBean lvfb = new org.springframework.validation.beanvalidation.LocalValidatorFactoryBean();
        lvfb.setProviderClass(org.hibernate.validator.HibernateValidator.class);
        lvfb.setValidationMessageSource(messageSource());
        return lvfb;
    }
    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("messages");
        messageSource.setDefaultEncoding("UTF-8");
        messageSource.setCacheSeconds(60);
        messageSource.setUseCodeAsDefaultMessage(false);
        return messageSource;
    }
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourceConfigurer() {
        PropertySourcesPlaceholderConfigurer pp = new PropertySourcesPlaceholderConfigurer();
        pp.setIgnoreUnresolvablePlaceholders(true);
        return pp;
    }
    //Cookie
    @Bean(name = "cookieConfig")
    public CookieMetaConfig getCookieConfig() {
        return new com.apobates.forum.member.storage.cookie.CookieMetaConfig(cookieName, cookieDomain, cookiePath, siteDomain);
    }
    
    @Bean(name = "onlineMemberStorage")
    public OnlineMemberStorage getMemberStorage(CookieMetaConfig cookieConfig) {
        return new com.apobates.forum.member.storage.cookie.HttpCookieProvider(cookieConfig);
    }
    
    @Bean(name="imageStoreDomain")
    public ImageStoreDomain getImageStore(){
        return new com.apobates.forum.attention.ImageStoreDomain(){
            @Override
            public String getDefaultDomain() {
                return imageBucketDomain;
            }
            
            @Override
            public String getLocalDomain() {
                return siteDomain;
            }
        };
    }
    
    @Bean(name="imageIOMeta")
    public ImageIOMeta getImageIOMeta(){
        return new com.apobates.forum.core.ImageIOMeta(){
            @Override
            public String getImageBucketDomain() {
                return imageBucketDomain;
            }
            
            @Override
            public String getUploadImageDirectName() {
                return imageBucketUploadDirect;
            }
        };
    }
}