package com.airlock.iam.authentication.infrastructure;

import com.airlock.iam.authentication.api.infrastructure.AuthenticationExtension;
import com.airlock.iam.authentication.infrastructure.factory.saml2.Saml2IdentityPropagatorModule;
import com.airlock.iam.authentication.infrastructure.factory.saml2.Saml2SpSsoInitModule;
import com.airlock.iam.authentication.infrastructure.resource.Airlock2FAActivationAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.Airlock2FAAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.Airlock2FARecoveryAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.ApplicationAccessByAppIdFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.ApplicationAccessByOAuth2AuthorizationResource;
import com.airlock.iam.authentication.infrastructure.resource.ApplicationAccessByURIFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.ApplicationAccessDefaultApplicationResource;
import com.airlock.iam.authentication.infrastructure.resource.AuthenticationAcknowledgeMessageFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.AuthenticationDynamicStepActivationResource;
import com.airlock.iam.authentication.infrastructure.resource.AuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.AuthenticationInteractiveGotoResource;
import com.airlock.iam.authentication.infrastructure.resource.AuthenticationInteractiveSelectionResource;
import com.airlock.iam.authentication.infrastructure.resource.AuthenticationTermsOfServiceFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.AuthenticationUiConfigurationResource;
import com.airlock.iam.authentication.infrastructure.resource.CrontoActivationAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.CrontoAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.CrontoPushActivationAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.CurrentAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.DeviceTokenFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.DeviceTokenRegistrationAuthFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.EmailOtpAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.EmailVerificationAuthFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.FidoAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.FidoRegistrationAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.GenericOtpAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.KerberosAuthenticationResource;
import com.airlock.iam.authentication.infrastructure.resource.LocationInterpretationResource;
import com.airlock.iam.authentication.infrastructure.resource.MatrixAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.MigrationResource;
import com.airlock.iam.authentication.infrastructure.resource.MtanAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.MtanRegistrationAuthResource;
import com.airlock.iam.authentication.infrastructure.resource.OAuth2ClientAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.OAuth2ConsentFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.OAuth2UiConfigurationResource;
import com.airlock.iam.authentication.infrastructure.resource.OathOtpActivationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.OathOtpAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.PasswordAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.Saml2IdpAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.Saml2SpAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.SecretQuestionsProvisioningFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.SsiAuthResource;
import com.airlock.iam.authentication.infrastructure.resource.UserDataEditAuthFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.UserIdentificationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.UsernamePasswordAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.VascoOtpAuthenticationFlowResource;
import com.airlock.iam.authentication.infrastructure.resource.oneshot.OneShotAuthenticationResource;
import com.airlock.iam.common.api.application.configuration.RestApplicationConfiguration;
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.common.infrastructure.reporting.factory.RequestEnvironmentReportingDataModule;
import com.airlock.iam.flow.shared.infrastructure.factory.step.Airlock2FADeleteDevicesStepModule;
import com.airlock.iam.flow.shared.infrastructure.factory.valueprovider.Airlock2FACooldownPredicateModule;
import com.airlock.iam.flow.shared.infrastructure.factory.valueprovider.Airlock2FADeviceUsedForLoginPredicateModule;
import com.airlock.iam.flow.shared.infrastructure.factory.valueprovider.Airlock2FALoginDeviceUnlessLastDeviceIdProviderModule;
import com.airlock.iam.flow.shared.infrastructure.filter.general.FlowSessionCleanupResponseFilter;
import com.airlock.iam.flow.shared.infrastructure.filter.general.TagRemovalFilter;
import com.airlock.iam.flow.shared.infrastructure.filter.general.UserPrincipalSaveFilter;
import com.airlock.iam.flow.shared.infrastructure.filter.general.UserSessionCleanupResponseFilter;
import com.airlock.iam.keymanagementservice.infrastructure.factory.AwsKmsModule;
import com.airlock.iam.keymanagementservice.infrastructure.factory.AwsKmsPasswordDecryptionModule;
import com.airlock.iam.oauth2.infrastructure.factory.OAuth2ClientIdPatternUiTenantIdRuleModule;
import com.airlock.iam.oauth2.infrastructure.factory.rest.session.OAuth2ExtendedSessionRepositoryModule;
import com.airlock.iam.oauth2.infrastructure.factory.shared.OAuth2AuthorizationServerConfigModule;
import com.airlock.iam.oauth2.infrastructure.factory.shared.OAuth2ScopeTranslatorModule;
import com.airlock.iam.oauth2.infrastructure.factory.valueprovider.OAuth2AccessTokenValueProviderModule;
import com.airlock.iam.oauth2.infrastructure.filter.OpenIDProviderUserAgentStateCleanupResponseFilter;
import com.airlock.iam.saml2.infrastructure.factory.FlowFederationSessionRepositoryModule;
import com.airlock.iam.saml2.infrastructure.factory.Saml2ConfigModule;
import com.airlock.iam.saml2.infrastructure.factory.Saml2FlowFederationSessionTerminationServiceModule;
import com.airlock.iam.saml2.infrastructure.factory.Saml2RequestAndResponseModule;
import com.airlock.iam.saml2.infrastructure.factory.idp.Saml2SpEntityIdPatternUiTenantIdRuleModule;
import com.airlock.iam.saml2.infrastructure.factory.sp.Saml2AttributeNameToTagMappingModule;
import com.airlock.iam.saml2.infrastructure.factory.sp.Saml2FlowSpConfigServiceModule;
import com.airlock.iam.saml2.infrastructure.factory.sp.Saml2UserIdentifyingStepModule;
import com.airlock.iam.saml2.infrastructure.filter.Saml2BlockRestRequestsFilter;
import com.airlock.iam.saml2.infrastructure.jersey.filter.Saml2RequestThreadContextFilter;
import com.airlock.iam.ssi.infrastructure.factory.ProcivisCoreSsiServiceModule;
import com.airlock.iam.ssi.infrastructure.factory.ProcivisDeskSsiServiceModule;
import com.airlock.iam.ssi.infrastructure.factory.SsiAuthenticationStepModule;
import com.airlock.iam.ssi.infrastructure.factory.SsiPasswordlessAuthenticationStepModule;
import com.airlock.iam.ssi.infrastructure.factory.SsiPersistedIssuanceStepModule;
import com.airlock.iam.ssi.infrastructure.factory.SsiSelfRegistrationIssuanceStepModule;
import com.airlock.iam.ssi.infrastructure.factory.SsiVerificationStepModule;
import com.google.inject.Module;
import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;

@RestApplicationConfiguration(
   dependencyProviders = {
         "com.airlock.iam.authentication.infrastructure.factory",
         "com.airlock.iam.base.infrastructure.factory",
         "com.airlock.iam.common.infrastructure.factory",
         "com.airlock.iam.fido.login.infrastructure.factory",
         "com.airlock.iam.flow.shared.infrastructure.factory",
         "com.airlock.iam.flow.ui.infrastructure.factory",
         "com.airlock.iam.login.app.infrastructure.factory.oauth2.shared",
         "com.airlock.iam.login.app.infrastructure.factory.pub",
         "com.airlock.iam.login.app.infrastructure.factory.shared",
         "com.airlock.iam.login.rest.infrastructure.factory.event",
         "com.airlock.iam.login.rest.infrastructure.factory.shared",
         "com.airlock.iam.oauth2.infrastructure.factory.flow"
   },
   domainEventSubscribers = {
         "com.airlock.iam.authentication.application.service.event.subscriber", "com.airlock.iam.login.application.service.event.subscriber"
   },
   exceptionMappers = {
         "com.airlock.iam.common.infrastructure.exception",
         "com.airlock.iam.flow.shared.infrastructure.exception",
         "com.airlock.iam.login.rest.infrastructure.exception.shared"
   },
   beanMappers = {
         "com.airlock.iam.authentication.infrastructure.mapper",
         "com.airlock.iam.common.infrastructure.mapper",
         "com.airlock.iam.flow.shared.infrastructure.mapper",
         "com.airlock.iam.flow.ui.infrastructure.mapper"
   }
)
public final class MainAuthenticationExtension implements AuthenticationExtension {
   @Override
   public Collection<Class<? extends Module>> guiceModules() {
      return List.of(
         Airlock2FACooldownPredicateModule.class,
         Airlock2FADeleteDevicesStepModule.class,
         Airlock2FADeviceUsedForLoginPredicateModule.class,
         Airlock2FALoginDeviceUnlessLastDeviceIdProviderModule.class,
         AwsKmsModule.class,
         AwsKmsPasswordDecryptionModule.class,
         FlowFederationSessionRepositoryModule.class,
         OAuth2AccessTokenValueProviderModule.class,
         OAuth2AuthorizationServerConfigModule.class,
         OAuth2ClientIdPatternUiTenantIdRuleModule.class,
         OAuth2ScopeTranslatorModule.class,
         OAuth2ExtendedSessionRepositoryModule.class,
         ProcivisCoreSsiServiceModule.class,
         ProcivisDeskSsiServiceModule.class,
         RequestEnvironmentReportingDataModule.class,
         Saml2AttributeNameToTagMappingModule.class,
         Saml2ConfigModule.class,
         Saml2FlowFederationSessionTerminationServiceModule.class,
         Saml2FlowSpConfigServiceModule.class,
         Saml2IdentityPropagatorModule.class,
         Saml2RequestAndResponseModule.class,
         Saml2SpEntityIdPatternUiTenantIdRuleModule.class,
         Saml2SpSsoInitModule.class,
         Saml2UserIdentifyingStepModule.class,
         SsiAuthenticationStepModule.class,
         SsiPersistedIssuanceStepModule.class,
         SsiSelfRegistrationIssuanceStepModule.class,
         SsiPasswordlessAuthenticationStepModule.class,
         SsiVerificationStepModule.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,
         FlowSessionCleanupResponseFilter.class,
         CombinedRequestDelayAndIamSessionFilter.class,
         LegacyInjectorInitFilter.class,
         LogContextFilter.class,
         MediaTypeNormalizationFilter.class,
         NoCacheFilter.class,
         OpenIDProviderUserAgentStateCleanupResponseFilter.class,
         Saml2RequestThreadContextFilter.class,
         SessionTerminationResponseFilter.class,
         SessionTimeoutResponseFilter.class,
         SystemAvailabilityFilter.class,
         TagRemovalFilter.class,
         UserPrincipalSaveFilter.class,
         UserSessionCleanupResponseFilter.class,
         Saml2BlockRestRequestsFilter.class
      );
   }

   private static Stream<Class<?>> restResources() {
      return Stream.of(
         Airlock2FAActivationAuthenticationFlowResource.class,
         Airlock2FAAuthenticationFlowResource.class,
         Airlock2FARecoveryAuthenticationFlowResource.class,
         ApplicationAccessByAppIdFlowResource.class,
         ApplicationAccessByOAuth2AuthorizationResource.class,
         ApplicationAccessByURIFlowResource.class,
         ApplicationAccessDefaultApplicationResource.class,
         AuthenticationAcknowledgeMessageFlowResource.class,
         AuthenticationDynamicStepActivationResource.class,
         AuthenticationFlowResource.class,
         AuthenticationInteractiveGotoResource.class,
         AuthenticationInteractiveSelectionResource.class,
         AuthenticationTermsOfServiceFlowResource.class,
         AuthenticationUiConfigurationResource.class,
         CrontoActivationAuthenticationFlowResource.class,
         CrontoAuthenticationFlowResource.class,
         CrontoPushActivationAuthenticationFlowResource.class,
         CurrentAuthenticationFlowResource.class,
         DeviceTokenFlowResource.class,
         DeviceTokenRegistrationAuthFlowResource.class,
         EmailOtpAuthenticationFlowResource.class,
         EmailVerificationAuthFlowResource.class,
         FidoAuthenticationFlowResource.class,
         FidoRegistrationAuthenticationFlowResource.class,
         GenericOtpAuthenticationFlowResource.class,
         KerberosAuthenticationResource.class,
         LocationInterpretationResource.class,
         MatrixAuthenticationFlowResource.class,
         MigrationResource.class,
         MtanAuthenticationFlowResource.class,
         MtanRegistrationAuthResource.class,
         OAuth2ClientAuthenticationFlowResource.class,
         OAuth2ConsentFlowResource.class,
         OAuth2UiConfigurationResource.class,
         OathOtpActivationFlowResource.class,
         OathOtpAuthenticationFlowResource.class,
         OneShotAuthenticationResource.class,
         PasswordAuthenticationFlowResource.class,
         Saml2IdpAuthenticationFlowResource.class,
         Saml2SpAuthenticationFlowResource.class,
         SecretQuestionsProvisioningFlowResource.class,
         SsiAuthResource.class,
         UserDataEditAuthFlowResource.class,
         UserIdentificationFlowResource.class,
         UsernamePasswordAuthenticationFlowResource.class,
         VascoOtpAuthenticationFlowResource.class
      );
   }
}
