package com.airlock.iam.authentication.infrastructure.factory;

import com.airlock.iam.authentication.application.service.oauth2.OAuth2AuthorizationService;
import com.airlock.iam.authentication.application.service.oauth2.OpenIdConnectPromptNoneAuthorizationService;
import com.airlock.iam.authentication.application.service.oauth2.OpenIdConnectPromptNoneAuthorizationServiceImpl;
import com.airlock.iam.authentication.application.service.oauth2.OpenIdConnectPromptNoneFlowResultHandler;
import com.airlock.iam.authentication.application.service.oauth2.OpenIdConnectPromptNoneFlowResultHandlerImpl;
import com.airlock.iam.authentication.application.service.targetapp.TargetApplicationRepository;
import com.airlock.iam.base.api.infrastructure.plugin.PluginConfigToLogic;
import com.airlock.iam.flow.api.domain.model.flow.ApplicationId;
import com.airlock.iam.oauth2.application.configuration.OAuth2AuthorizationServerConfigSpec;
import com.airlock.iam.oauth2.domain.model.authentication.OpenIdConnectLoginHintFlowHandler;
import com.airlock.iam.oauth2.domain.model.settings.OAuth2ApplicationFlowSelectionSettings;
import com.airlock.iam.oauth2.domain.model.settings.OAuth2OidcAuthorizationCodeGrantSettings;
import com.airlock.iam.oauth2.domain.service.OpenIdProviderUserAgentStateService;
import com.airlock.iam.oauth2.domain.service.codegrant.CommonAuthorizationCodeRequestValidator;
import com.airlock.iam.oauth2.domain.service.codegrant.DefaultOpenIdConnectUserSessionValidationService;
import com.airlock.iam.oauth2.domain.service.codegrant.OAuth2AuthorizationCodeRequestValidator;
import com.airlock.iam.oauth2.domain.service.codegrant.OAuth2AuthorizationCodeRequestValidatorImpl;
import com.airlock.iam.oauth2.domain.service.codegrant.OpenIdConnectAuthenticationCodeRequestValidator;
import com.airlock.iam.oauth2.domain.service.codegrant.OpenIdConnectAuthenticationRequestValidatorImpl;
import com.airlock.iam.oauth2.domain.service.codegrant.OpenIdConnectUserSessionValidationService;
import com.airlock.iam.oauth2.domain.service.consent.OpenIdProviderUserAgentStateServiceImpl;
import com.google.inject.PrivateModule;
import com.google.inject.Provides;
import java.util.Optional;
import java.util.function.Supplier;

public class OAuth2AuthorizationServiceModule extends PrivateModule {
   @Provides
   Optional<OpenIdConnectLoginHintFlowHandler> provideLoginHintHandler(OAuth2AuthorizationServerConfigSpec asConfig, PluginConfigToLogic toLogic) {
      return asConfig.getLoginHintFlowConfig().map(toLogic::getLogic);
   }

   @Provides
   Supplier<ApplicationId> provideDefaultApplication(TargetApplicationRepository applicationRepository) {
      return () -> applicationRepository.getDefaultApplication().getApplicationId();
   }

   @Provides
   OAuth2ApplicationFlowSelectionSettings provideFlowSelectionSettings(OAuth2OidcAuthorizationCodeGrantSettings oAuth2AuthorizationCodeGrantSettings) {
      return oAuth2AuthorizationCodeGrantSettings.getFlowSelectionSettings();
   }

   protected void configure() {
      this.bind(OpenIdProviderUserAgentStateService.class).to(OpenIdProviderUserAgentStateServiceImpl.class);
      this.bind(OAuth2AuthorizationCodeRequestValidator.class).to(OAuth2AuthorizationCodeRequestValidatorImpl.class);
      this.bind(OpenIdConnectAuthenticationCodeRequestValidator.class).to(OpenIdConnectAuthenticationRequestValidatorImpl.class);
      this.bind(CommonAuthorizationCodeRequestValidator.class);
      this.bind(OpenIdConnectPromptNoneAuthorizationService.class).to(OpenIdConnectPromptNoneAuthorizationServiceImpl.class);
      this.expose(OpenIdConnectPromptNoneAuthorizationService.class);
      this.bind(OpenIdConnectUserSessionValidationService.class).to(DefaultOpenIdConnectUserSessionValidationService.class);
      this.bind(OAuth2AuthorizationService.class);
      this.expose(OAuth2AuthorizationService.class);
      this.bind(OpenIdProviderUserAgentStateService.class).to(OpenIdProviderUserAgentStateServiceImpl.class);
      this.bind(OpenIdConnectPromptNoneFlowResultHandler.class).to(OpenIdConnectPromptNoneFlowResultHandlerImpl.class);
   }
}
