package org.ros.chatto;

import org.ros.chatto.logged.UserSessionLoggingLoginSuccessHandler;
import org.ros.chatto.logged.UserSessionLoggingLogoutSuccessHandler;
import org.ros.chatto.security.CustomBasicAuthenticationFilter;
import org.ros.chatto.security.MyUserDetailsService;
import org.ros.chatto.security.TokenAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

	@Autowired
	private MyUserDetailsService myUserDetailsService;
	@Autowired
	private PasswordEncoder passwordEncoder;

	@Override
	@Bean
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}

	@Bean
	public AuthenticationProvider authenticationProvider() {
		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
		provider.setUserDetailsService(myUserDetailsService);
		provider.setPasswordEncoder(passwordEncoder);
		return provider;
	}

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

	@Configuration
	@Order(1)
	public static class ApiWebSecurity extends WebSecurityConfigurerAdapter {
		@Autowired
		private RESTAuthenticationEntryPoint authenticationEntryPoint;
		
		@Autowired
		private CustomBasicAuthenticationFilter customBasicAuthFilter;

		@Autowired
		private TokenAuthenticationFilter tokenFilter;

		@Override
		protected void configure(HttpSecurity http) throws Exception {
			http.csrf().disable().exceptionHandling()

					.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
//					.cors().and()
					
					.antMatcher("/api/**").authorizeRequests()
					.antMatchers("/api/chat/**").hasAnyRole("USER", "ADMIN", "SUPER_USER")
					.antMatchers("/api/demo/**").hasRole("SUPER_USER")
//					.antMatchers("/perform-login").permitAll()
					
					.anyRequest()
//					.hasAnyRole("USER", "ADMIN", "SUPER_USER")
					.authenticated()
					.and().httpBasic().authenticationEntryPoint(authenticationEntryPoint)
			;
			
			http.addFilterBefore(tokenFilter, BasicAuthenticationFilter.class);

			// Creating token when basic authentication is successful and the same token can
			// be used to authenticate for further requests
//			final CustomBasicAuthenticationFilter customBasicAuthFilter = new CustomBasicAuthenticationFilter(
//					authenticationManagerBean());
			http.addFilter(customBasicAuthFilter);

		}

	}

	@Configuration
	@Order(2)
	public static class FormWebSecurity extends WebSecurityConfigurerAdapter {
		@Autowired
		private UserSessionLoggingLoginSuccessHandler loginSuccessHandler;

		@Autowired
		private UserSessionLoggingLogoutSuccessHandler logoutSuccessHandler;

		@Override
		protected void configure(HttpSecurity httpSecurity) throws Exception {
			httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS).and()

					.authorizeRequests()
//            		.antMatchers(HttpMethod.POST, "/api/**").permitAll()
					.antMatchers("/", "perform_login", "/logout**", "/favicon.ico", "/login*", "/registration",
							"/perform_registration", "/css/**", "/js/**", "/img/**")
					.permitAll()
//                    .antMatchers("/","/api**","/api/**","/login*","/registration","/perform_registration","/css/**", "/js/**", "/images/**").permitAll()
					.antMatchers("/user/**").hasAnyRole("USER", "ADMIN", "SUPER_USER").antMatchers("/admin/**")
					.hasAnyRole("ADMIN", "SUPER_USER")
//					.and()
//					.antMatcher("/api/**")
//					.authorizeRequests()
					.anyRequest().authenticated()

					.and()

					.formLogin().loginPage("/login").permitAll().loginProcessingUrl("/perform_login")
					.successHandler(loginSuccessHandler).and().logout()
					.logoutSuccessHandler(logoutSuccessHandler)
			;
		}
//	    }

	}
}
