package com.airlock.iam.flow.shared.infrastructure;

import com.airlock.iam.common.api.domain.model.user.UsernameToPropagate;
import com.airlock.iam.common.application.service.DefaultSessionTerminationService;
import com.airlock.iam.common.application.service.session.SessionTerminationService;
import com.airlock.iam.flow.api.domain.model.session.FlowSession;
import com.airlock.iam.flow.domain.model.flow.OptionalFlow;
import com.airlock.iam.flow.domain.model.session.InternalFlowSession;
import com.airlock.iam.flow.infrastructure.serialization.NoStateMachineSerializer;
import com.airlock.iam.flow.infrastructure.serialization.StateMachineSerializer;
import com.airlock.iam.flow.shared.api.domain.model.session.UserDependentFlowSession;
import com.airlock.iam.flow.shared.application.configuration.FlowUserNameTransformerConfig;
import com.airlock.iam.flow.shared.domain.model.session.FlowSessionImpl;
import com.airlock.iam.flow.shared.domain.model.user.UserLoginStatistics;
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 NoFlowModule extends PrivateModule {
   @Provides
   @Exposed
   FlowSessionImpl provideFlowSession() {
      throw new UnsupportedOperationException("FlowSession not provided");
   }

   protected void configure() {
      this.bind(new TypeLiteral<Optional<FlowUserNameTransformerConfig>>() {}).toInstance(Optional.empty());
      this.expose(new TypeLiteral<Optional<FlowUserNameTransformerConfig>>() {});
      this.bind(SessionTerminationService.class).to(DefaultSessionTerminationService.class).in(RequestScoped.class);
      this.expose(SessionTerminationService.class);
      this.bind(StateMachineSerializer.class).toInstance(new NoStateMachineSerializer());
      this.expose(StateMachineSerializer.class);
      this.bind(OptionalFlow.class).toInstance(OptionalFlow.withoutFlow());
      this.expose(OptionalFlow.class);
      this.bind(FlowSession.class).to(FlowSessionImpl.class);
      this.expose(FlowSession.class);
      this.bind(InternalFlowSession.class).to(FlowSessionImpl.class);
      this.expose(InternalFlowSession.class);
      this.bind(UserDependentFlowSession.class).to(FlowSessionImpl.class);
      this.expose(UserDependentFlowSession.class);
      this.bind(new TypeLiteral<Optional<UsernameToPropagate>>() {}).toInstance(Optional.empty());
      this.expose(new TypeLiteral<Optional<UsernameToPropagate>>() {});
      this.bind(new TypeLiteral<Optional<UserLoginStatistics>>() {}).toInstance(Optional.empty());
      this.expose(new TypeLiteral<Optional<UserLoginStatistics>>() {});
   }
}
