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

import com.airlock.iam.common.application.configuration.state.IamSessionSameSitePolicy;
import com.airlock.iam.common.domain.model.state.StateTimeout;
import com.airlock.iam.common.domain.service.mapification.Mapifier;
import com.airlock.iam.common.domain.service.session.CorrelationIdService;
import com.airlock.iam.common.domain.service.session.IamSessionRepository;
import com.airlock.iam.common.domain.service.session.IamSessionService;
import com.airlock.iam.common.domain.service.session.NoSessionTicketRestore;
import com.airlock.iam.common.domain.service.session.SessionTicketRestore;
import com.airlock.iam.common.infrastructure.mapification.MapifierImpl;
import com.airlock.iam.common.infrastructure.session.CorrelationIdServiceImpl;
import com.airlock.iam.common.infrastructure.session.IamSessionServiceImpl;
import com.airlock.iam.flow.shared.domain.model.session.FlowAttributeRepositoryMapifier;
import com.airlock.iam.flow.shared.domain.model.session.FlowBasedIamSession;
import com.airlock.iam.flow.shared.domain.model.session.FlowSessionMapifier;
import com.airlock.iam.flow.shared.domain.model.session.FlowSessionTagsMapifier;
import com.airlock.iam.flow.shared.domain.model.session.MultiFlowSessionMapifier;
import com.airlock.iam.flow.shared.domain.model.session.StepResultMapifier;
import com.airlock.iam.flow.shared.domain.service.session.ReadOnlyIamSessionDataFactory;
import com.airlock.iam.flow.shared.domain.service.session.ReadOnlyIamSessionDataFactoryImpl;
import com.airlock.iam.flow.shared.domain.service.session.ReadOnlyUserSessionDataFactory;
import com.airlock.iam.flow.shared.domain.service.tag.TagMapifier;
import com.airlock.iam.flow.shared.infrastructure.factory.tag.TagMapifierImpl;
import com.airlock.iam.flow.shared.infrastructure.service.UserSessionMapifier;
import com.airlock.iam.flow.shared.infrastructure.session.FlowAttributeRepositoryMapifierImpl;
import com.airlock.iam.flow.shared.infrastructure.session.FlowBasedIamSessionRepository;
import com.airlock.iam.flow.shared.infrastructure.session.FlowBasedIamSessionSerializer;
import com.airlock.iam.flow.shared.infrastructure.session.FlowBasedIamSessionSerializerImpl;
import com.airlock.iam.flow.shared.infrastructure.session.FlowSessionMapifierImpl;
import com.airlock.iam.flow.shared.infrastructure.session.FlowSessionTagsMapifierImpl;
import com.airlock.iam.flow.shared.infrastructure.session.UserSessionMapifierImpl;
import com.airlock.iam.login.infrastructure.session.MultiFlowSessionMapifierImpl;
import com.airlock.iam.login.infrastructure.session.StepResultMapifierImpl;
import com.airlock.iam.transactionapproval.application.configuration.TransactionApprovalApp;
import com.airlock.iam.transactionapproval.domain.model.TransactionApprovalReadOnlyUserSessionDataFactory;
import com.google.inject.Exposed;
import com.google.inject.PrivateModule;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
import com.google.inject.servlet.RequestScoped;
import java.util.Optional;

public final class TransactionApprovalIamSessionServiceModule extends PrivateModule {
   @Provides
   @Exposed
   @RequestScoped
   Optional<IamSessionService<?>> provideOptionalIamSessionService(IamSessionService<FlowBasedIamSession> iamSessionService) {
      return Optional.of(iamSessionService);
   }

   @Provides
   @RequestScoped
   StateTimeout provideDefaultStateTimeout(TransactionApprovalApp transactionApprovalApp) {
      return StateTimeout.timeout(transactionApprovalApp.getSessionIdleTimeout(), Optional.of(transactionApprovalApp.getSessionLifetime()));
   }

   protected void configure() {
      this.bind(TagMapifier.class).to(TagMapifierImpl.class).in(RequestScoped.class);
      this.expose(TagMapifier.class);
      this.bind(Mapifier.class).to(MapifierImpl.class).in(RequestScoped.class);
      this.expose(Mapifier.class);
      this.bind(FlowSessionTagsMapifier.class).to(FlowSessionTagsMapifierImpl.class);
      this.bind(FlowAttributeRepositoryMapifier.class).to(FlowAttributeRepositoryMapifierImpl.class);
      this.bind(StepResultMapifier.class).to(StepResultMapifierImpl.class);
      this.expose(StepResultMapifier.class);
      this.bind(UserSessionMapifier.class).to(UserSessionMapifierImpl.class);
      this.bind(FlowSessionMapifier.class).to(FlowSessionMapifierImpl.class);
      this.bind(MultiFlowSessionMapifier.class).to(MultiFlowSessionMapifierImpl.class);
      this.bind(FlowBasedIamSessionSerializer.class).to(FlowBasedIamSessionSerializerImpl.class);
      this.bind(CorrelationIdService.class).to(CorrelationIdServiceImpl.class).in(RequestScoped.class);
      this.bind(new TypeLiteral<SessionTicketRestore<FlowBasedIamSession>>() {}).toInstance(new NoSessionTicketRestore());
      this.bind(ReadOnlyIamSessionDataFactory.class).to(ReadOnlyIamSessionDataFactoryImpl.class);
      this.bind(ReadOnlyUserSessionDataFactory.class).to(TransactionApprovalReadOnlyUserSessionDataFactory.class);
      this.expose(ReadOnlyIamSessionDataFactory.class);
      this.bind(new TypeLiteral<IamSessionRepository<FlowBasedIamSession>>() {}).to(FlowBasedIamSessionRepository.class).in(RequestScoped.class);
      this.bind(new TypeLiteral<IamSessionService<FlowBasedIamSession>>() {})
         .to(new TypeLiteral<IamSessionServiceImpl<FlowBasedIamSession>>() {})
         .in(RequestScoped.class);
      this.expose(new TypeLiteral<IamSessionService<FlowBasedIamSession>>() {});
      this.bind(new TypeLiteral<IamSessionService<?>>() {}).to(new TypeLiteral<IamSessionServiceImpl<FlowBasedIamSession>>() {}).in(RequestScoped.class);
      this.expose(new TypeLiteral<IamSessionService<?>>() {});
      this.bind(IamSessionSameSitePolicy.class).toInstance(IamSessionSameSitePolicy.STRICT);
      this.expose(IamSessionSameSitePolicy.class);
   }
}
