package com.airlock.iam.oauth2.infrastructure;

import com.airlock.iam.common.api.application.configuration.RestApplicationConfiguration;
import com.airlock.iam.common.infrastructure.event.NoConfiguredEventSubscribersModule;
import com.airlock.iam.common.infrastructure.filter.general.CharsetResponseFilter;
import com.airlock.iam.common.infrastructure.filter.general.CombinedRequestDelayAndIamSessionFilter;
import com.airlock.iam.common.infrastructure.filter.general.ConfigurationLicensedFilter;
import com.airlock.iam.common.infrastructure.filter.general.ConfigurationPresentFilter;
import com.airlock.iam.common.infrastructure.filter.general.EnterExitFilter;
import com.airlock.iam.common.infrastructure.filter.general.LegacyInjectorInitFilter;
import com.airlock.iam.common.infrastructure.filter.general.LogContextFilter;
import com.airlock.iam.common.infrastructure.filter.general.MediaTypeNormalizationFilter;
import com.airlock.iam.common.infrastructure.filter.general.NoCacheFilter;
import com.airlock.iam.common.infrastructure.filter.general.SessionTerminationResponseFilter;
import com.airlock.iam.common.infrastructure.filter.general.SessionTimeoutResponseFilter;
import com.airlock.iam.common.infrastructure.filter.general.SystemAvailabilityFilter;
import com.airlock.iam.common.infrastructure.filter.security.CorsFilter;
import com.airlock.iam.common.infrastructure.filter.security.CsrfProtectionFilter;
import com.airlock.iam.flow.shared.infrastructure.NoFlowModule;
import com.airlock.iam.flow.shared.infrastructure.factory.FlowAttributesModule;
import com.airlock.iam.flow.shared.infrastructure.factory.SingleRequestPerUserServiceModule;
import com.airlock.iam.flow.shared.infrastructure.factory.UserSessionModule;
import com.airlock.iam.oauth2.api.infrastructure.OAuth2RestExtension;
import com.airlock.iam.oauth2.infrastructure.parameter.OAuth2SessionIdProvider;
import com.airlock.iam.oauth2.infrastructure.resource.rest.OAuth2CurrentSessionResource;
import com.airlock.iam.oauth2.infrastructure.resource.rest.OAuth2DiscoveryEndpointResource;
import com.airlock.iam.oauth2.infrastructure.resource.rest.OAuth2JwksResource;
import com.airlock.iam.oauth2.infrastructure.resource.rest.OAuth2MetadataEndpointResource;
import com.airlock.iam.oauth2.infrastructure.resource.rest.OAuth2ParEndpointResource;
import com.airlock.iam.oauth2.infrastructure.resource.rest.OAuth2ResourceEndpointResource;
import com.airlock.iam.oauth2.infrastructure.resource.rest.OAuth2SessionResource;
import com.airlock.iam.oauth2.infrastructure.resource.rest.OAuth2SessionsResource;
import com.airlock.iam.oauth2.infrastructure.resource.rest.OAuth2TokenEndpointResource;
import com.airlock.iam.oauth2.infrastructure.resource.rest.OAuth2TokenIntrospectionResource;
import com.airlock.iam.oauth2.infrastructure.resource.rest.OAuth2TokenRevocationResource;
import com.airlock.iam.oauth2.infrastructure.resource.rest.OpenIdConnectSessionManagementResource;
import com.airlock.iam.oauth2.infrastructure.resource.rest.OpenIdConnectUserInfoEndpointResource;
import com.google.inject.Module;
import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;

@RestApplicationConfiguration(
   dependencyProviders = {
         "com.airlock.iam.base.infrastructure.factory",
         "com.airlock.iam.common.infrastructure.factory",
         "com.airlock.iam.login.app.infrastructure.factory.oauth2.rest",
         "com.airlock.iam.login.app.infrastructure.factory.oauth2.shared",
         "com.airlock.iam.login.app.infrastructure.factory.shared",
         "com.airlock.iam.login.rest.infrastructure.factory.shared",
         "com.airlock.iam.oauth2.infrastructure.factory.rest",
         "com.airlock.iam.oauth2.infrastructure.factory.shared"
   },
   exceptionMappers = {"com.airlock.iam.common.infrastructure.exception", "com.airlock.iam.oauth2.infrastructure.exception.rest"},
   beanMappers = {"com.airlock.iam.common.infrastructure.mapper", "com.airlock.iam.oauth2.infrastructure.mapper"}
)
public final class MainOAuth2RestExtension implements OAuth2RestExtension {
   @Override
   public Collection<Class<? extends Module>> guiceModules() {
      return List.of(
         FlowAttributesModule.class,
         NoConfiguredEventSubscribersModule.class,
         NoFlowModule.class,
         SingleRequestPerUserServiceModule.class,
         UserSessionModule.class
      );
   }

   @Override
   public Collection<Class<?>> jaxRsComponents() {
      return Stream.concat(restFilters(), restResources()).toList();
   }

   private static Stream<Class<?>> restFilters() {
      return Stream.of(
         CharsetResponseFilter.class,
         ConfigurationLicensedFilter.class,
         ConfigurationPresentFilter.class,
         CorsFilter.class,
         CsrfProtectionFilter.class,
         EnterExitFilter.class,
         CombinedRequestDelayAndIamSessionFilter.class,
         LegacyInjectorInitFilter.class,
         LogContextFilter.class,
         MediaTypeNormalizationFilter.class,
         NoCacheFilter.class,
         OAuth2SessionIdProvider.class,
         SessionTerminationResponseFilter.class,
         SessionTimeoutResponseFilter.class,
         SystemAvailabilityFilter.class
      );
   }

   private static Stream<Class<?>> restResources() {
      return Stream.of(
         OAuth2CurrentSessionResource.class,
         OAuth2DiscoveryEndpointResource.class,
         OAuth2JwksResource.class,
         OAuth2MetadataEndpointResource.class,
         OAuth2ParEndpointResource.class,
         OAuth2ResourceEndpointResource.class,
         OAuth2SessionResource.class,
         OAuth2SessionsResource.class,
         OAuth2TokenEndpointResource.class,
         OAuth2TokenIntrospectionResource.class,
         OAuth2TokenRevocationResource.class,
         OpenIdConnectSessionManagementResource.class,
         OpenIdConnectUserInfoEndpointResource.class
      );
   }
}
