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

import com.airlock.iam.base.api.domain.model.exception.FailureException;
import com.airlock.iam.flow.api.domain.model.session.FlowSession;
import com.airlock.iam.flow.api.domain.model.step.StepResult;
import com.airlock.iam.flow.domain.model.session.CurrentlyExpectedStepAction;
import com.airlock.iam.flow.domain.model.session.InternalFlowSession;
import com.airlock.iam.flow.shared.api.domain.model.session.UserDependentFlowSession;
import com.airlock.iam.flow.shared.domain.model.session.FlowSessionImpl;
import com.airlock.iam.flow.shared.domain.model.session.MultiFlowCapableUserSession;
import com.google.inject.Exposed;
import com.google.inject.PrivateModule;
import com.google.inject.Provides;

public final class FlowSessionModule extends PrivateModule {
   @Provides
   FlowSessionImpl provideFlowSessionImpl(MultiFlowCapableUserSession userSession) {
      return (FlowSessionImpl)userSession.getCurrentFlowSession().orElseThrow(() -> new FailureException("No current flow session"));
   }

   @Exposed
   @Provides
   CurrentlyExpectedStepAction provideCurrentlyExpectedNextStepAction(MultiFlowCapableUserSession userSession) {
      return new CurrentlyExpectedStepAction(userSession.getCurrentFlowSession().flatMap(InternalFlowSession::lastResult).flatMap(StepResult::nextAction));
   }

   protected void configure() {
      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);
   }
}
