package de.otto.edison.togglz.configuration;

import de.otto.edison.authentication.Credentials;
import de.otto.edison.togglz.DefaultTogglzConfig;
import de.otto.edison.togglz.FeatureClassProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.togglz.core.Feature;
import org.togglz.core.context.StaticFeatureManagerProvider;
import org.togglz.core.manager.FeatureManager;
import org.togglz.core.manager.TogglzConfig;
import org.togglz.core.repository.StateRepository;
import org.togglz.core.repository.cache.CachingStateRepository;
import org.togglz.core.user.SimpleFeatureUser;
import org.togglz.core.user.UserProvider;
import org.togglz.servlet.TogglzFilter;
import org.togglz.servlet.util.HttpServletRequestHolder;
import org.togglz.spring.manager.FeatureManagerFactory;

import javax.servlet.http.HttpServletRequest;
import java.util.Optional;

@Configuration
@EnableConfigurationProperties(TogglzProperties.class)
public class TogglzConfiguration {

    @Bean
    @ConditionalOnMissingBean(name = "togglzFilter")
    public FilterRegistrationBean<TogglzFilter> togglzFilter() {
        final FilterRegistrationBean<TogglzFilter> filterRegistration = new FilterRegistrationBean<>();
        filterRegistration.setFilter(new TogglzFilter());
        filterRegistration.addUrlPatterns("/*");
        return filterRegistration;
    }

    @Bean
    @ConditionalOnMissingBean(FeatureClassProvider.class)
    public FeatureClassProvider featureClassProvider() {
        return () -> Features.class;
    }

    @Bean
    @ConditionalOnMissingBean(UserProvider.class)
    public UserProvider userProvider() {
        return () -> {

            final HttpServletRequest request = HttpServletRequestHolder.get();

            final Optional<Credentials> credentials = Credentials.readFrom(request);
            final boolean isAdmin = true; // "admin".equals(username);

            return new SimpleFeatureUser((credentials.isPresent() ? credentials.get().getUsername() : null), isAdmin);
        };
    }

    @Bean
    @ConditionalOnMissingBean(TogglzConfig.class)
    public TogglzConfig togglzConfig(final StateRepository stateRepository,
                                     final FeatureClassProvider featureClassProvider,
                                     final TogglzProperties togglzProperties,
                                     final UserProvider userProvider) {
        final CachingStateRepository cachingStateRepository = new CachingStateRepository(stateRepository, togglzProperties.getCacheTtl());
        return new DefaultTogglzConfig(cachingStateRepository, userProvider, featureClassProvider);
    }

    @Bean
    public FeatureManager featureManager(final TogglzConfig togglzConfig) throws Exception {
        final FeatureManagerFactory featureManagerFactory = new FeatureManagerFactory();
        featureManagerFactory.setTogglzConfig(togglzConfig);
        final FeatureManager featureManager = featureManagerFactory.getObject();
        StaticFeatureManagerProvider.setFeatureManager(featureManager);  // this workaround should be fixed with togglz version 2.2
        return featureManager;
    }

    private enum Features implements Feature {
        /* no features */
    }
}

@@ -182,32 +182,86 @@
 eClassProvider;%0A
+import de.otto.edison.togglz.KFeatureManagerProvider;%0A
 import org.sprin
@@ -322,24 +322,24 @@
 issingBean;%0A
-
 import org.s
@@ -589,16 +589,126 @@
 ration;%0A
+import org.springframework.context.annotation.Primary;%0Aimport org.springframework.context.annotation.Profile;%0A
 import o
@@ -835,24 +835,78 @@
 ureManager;%0A
+import org.togglz.core.manager.FeatureManagerBuilder;%0A
 import org.t
@@ -981,32 +981,32 @@
 tateRepository;%0A
-
 import org.toggl
@@ -1045,32 +1045,76 @@
 tateRepository;%0A
+import org.togglz.core.spi.FeatureProvider;%0A
 import org.toggl
@@ -3193,24 +3193,76 @@
 %0A%0A    @Bean%0A
+    @ConditionalOnMissingBean(FeatureManager.class)%0A
     public F
@@ -3739,24 +3739,524 @@
 ger;%0A    %7D%0A%0A
+    @Bean%0A    @Primary%0A    @Profile(%22test%22)%0A    public FeatureManager testFeatureManager(final Optional%3CFeatureProvider%3E featureProvider) throws Exception %7B%0A%0A        FeatureManagerBuilder featureManagerBuilder = FeatureManagerBuilder.begin();%0A%0A        featureProvider.ifPresent(featureManagerBuilder::featureProvider);%0A%0A        FeatureManager featureManager = featureManagerBuilder.build();%0A        KFeatureManagerProvider.Companion.setInstance(featureManager);%0A        return featureManager;%0A    %7D%0A%0A
     private 

initialize feature manager to be able to use enum class togglz in tests