package my.modules.web.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.io.FileSystemResource;
import org.springframework.data.web.config.EnableSpringDataWebSupport;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.LocaleResolver;
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.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;

import java.io.IOException;
import java.util.Locale;

/**
 * This class allocates the web configuration.
 *
 * @author Kai Paroth
 */
@Configuration
@EnableWebMvc
@EnableSpringDataWebSupport
public class WebConfig extends WebMvcConfigurerAdapter {
    /**
     * The API URI.
     */
    public static final String URI_API = "/api";

    /**
     * The statics URI.
     */
    public static final String URI_STATIC = "/static";

    /**
     * The environment.
     */
    @Autowired
    private Environment environment;

    /**
     * The message source.
     */
    @Autowired
    private MessageSource messageSource;

    /**
     * Creates a new {@link CommonsMultipartResolver} instance.
     *
     * @return the instance.
     * @throws IOException if the upload temporary directory is not accessible.
     */
    @Bean
    public MultipartResolver multipartResolver() throws IOException {
        CommonsMultipartResolver bean = new CommonsMultipartResolver();
        bean.setDefaultEncoding(environment.getProperty("upload.encoding"));
        bean.setUploadTempDir(new FileSystemResource(environment.getProperty("upload.location")));
        bean.setMaxUploadSize(Long.parseLong(environment.getProperty("upload.maxRequestSize")));
        bean.setMaxUploadSizePerFile(Long.parseLong(environment.getProperty("upload.maxFileSize")));
        bean.setMaxInMemorySize(Integer.parseInt(environment.getProperty("upload.fileSizeThreshold")));

        return bean;
    }

    /**
     * Creates a new {@link LocaleResolver} instance.
     *
     * @return the instance.
     */
    @Bean
    public LocaleResolver localeResolver() {
        // NOTE: HTTP-Request header locale configuration!
        //SessionLocaleResolver bean = new SessionLocaleResolver();
        AcceptHeaderLocaleResolver bean = new AcceptHeaderLocaleResolver();
        bean.setDefaultLocale(new Locale("en"));

        return bean;
    }

    /**
     * Create a new {@link TilesConfigurer} instance.
     *
     * @return the instance.
     */
    @Bean
    public TilesConfigurer tilesConfigurer() {
        TilesConfigurer bean = new TilesConfigurer();
        bean.setDefinitions("/WEB-INF/views/**/tiles.xml");
        bean.setCheckRefresh(true);

        return bean;
    }

    /**
     * {@inheritDoc}.
     *
     * @see WebMvcConfigurerAdapter#configureViewResolvers(ViewResolverRegistry)
     */
    @Override
    public void configureViewResolvers(final ViewResolverRegistry registry) {
        registry.viewResolver(new TilesViewResolver());
    }

    /**
     * {@inheritDoc}.
     *
     * @see WebMvcConfigurerAdapter#getValidator()
     */
    @Override
    public Validator getValidator() {
        LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
        validator.setValidationMessageSource(messageSource);

        return validator;
    }

    /**
     * {@inheritDoc}.
     *
     * @see WebMvcConfigurerAdapter#addInterceptors(InterceptorRegistry)
     */
    @Override
    public void addInterceptors(final InterceptorRegistry registry) {
        // NOTE: HTTP-Request header locale configuration!
        //registry.addInterceptor(new LocaleChangeInterceptor()); // To change the locale via URL parameter "locale".
    }

    /**
     * {@inheritDoc}.
     *
     * @see WebMvcConfigurerAdapter#addViewControllers(ViewControllerRegistry)
     */
    @Override
    public void addViewControllers(final ViewControllerRegistry registry) {
        // registry.addViewController("/").setViewName("forward:/index.html");
    }

    /**
     * {@inheritDoc}.
     *
     * @see WebMvcConfigurerAdapter#addResourceHandlers(ResourceHandlerRegistry)
     */
    @Override
    public void addResourceHandlers(final ResourceHandlerRegistry registry) {
        registry.addResourceHandler(URI_STATIC + "/**")
                .addResourceLocations(URI_STATIC + "/");

        registry.addResourceHandler("/swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    /**
     * {@inheritDoc}.
     *
     * @see WebMvcConfigurerAdapter#configureDefaultServletHandling(DefaultServletHandlerConfigurer)
     */
    @Override
    public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}
