package com.tsi.sig.server.security;

import com.tsi.sig.server.service.LoginServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import javax.xml.ws.WebServiceException;
import java.util.Arrays;

@Slf4j
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
        securedEnabled = true
)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    private final LoginServiceImpl loginService;

    protected void configure(HttpSecurity http) throws Exception, WebServiceException {
        ((HttpSecurity)((FormLoginConfigurer)((FormLoginConfigurer)((HttpSecurity)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)
                ((HttpSecurity)http.headers().frameOptions().sameOrigin().and())
                        .authorizeRequests().antMatchers(new String[]{"/**"})).permitAll().and())
                .formLogin().loginPage("/showlogin.do").failureUrl("/denied.do"))
                .usernameParameter("userId").passwordParameter("userPswd").permitAll()).and())
                .logout().logoutUrl("/logout.do").invalidateHttpSession(true).logoutSuccessUrl("/showlogin.do");
        http.authorizeRequests().anyRequest().hasAnyRole("I", "B", "N", "M", "S");
        http.csrf().disable();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOrigin("*");
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS", "PUT", "DELETE"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Bean
    public static TSIEncoder passwordEncoder() {
        return new TSIEncoder();
    }

    public void configure(WebSecurity web) throws Exception, WebServiceException {
        web.ignoring().antMatchers("/css/**", "/js/**", "/images/**", "/actuator/**", "/denied.do");
    }

    public void configure(AuthenticationManagerBuilder auth) throws Exception, WebServiceException {
        auth.userDetailsService(this.loginService).passwordEncoder(passwordEncoder());
    }

    public WebSecurityConfig(final LoginServiceImpl loginService) {
        this.loginService = loginService;
    }
}
