class StateControllerFactory {

    public <T extends State> StateController build(final T state, final StateTransitionAction stateTransitionAction) {
        PolicyState policyState = PolicyState.fromStateClass(state.getClass());
        switch (policyState) {

            case SESSION_STARTED:
                return new SessionStartedStateController(
                        (SessionStartedState) state,
                        injector.getInstance(HubEventLogger.class),
                        stateTransitionAction,
                        injector.getInstance(TransactionsConfigProxy.class),
                        injector.getInstance(ResponseFromHubFactory.class),
                        injector.getInstance(IdentityProvidersConfigProxy.class));

            case EIDAS_COUNTRY_SELECTED:
                return new EidasCountrySelectedStateController(
                        (EidasCountrySelectedState) state,
                        injector.getInstance(HubEventLogger.class),
                        stateTransitionAction,
                        injector.getInstance(PolicyConfiguration.class),
                        injector.getInstance(TransactionsConfigProxy.class),
                        injector.getInstance(MatchingServiceConfigProxy.class),
                        injector.getInstance(ResponseFromHubFactory.class),
                        injector.getInstance(AssertionRestrictionsFactory.class));

            case IDP_SELECTED:
                return new IdpSelectedStateController(
                        (IdpSelectedState) state,
                        injector.getInstance(HubEventLogger.class),
                        stateTransitionAction,
                        injector.getInstance(IdentityProvidersConfigProxy.class),
                        injector.getInstance(TransactionsConfigProxy.class),
                        injector.getInstance(ResponseFromHubFactory.class),
                        injector.getInstance(PolicyConfiguration.class),
                        injector.getInstance(AssertionRestrictionsFactory.class),
                        injector.getInstance(MatchingServiceConfigProxy.class));

            case CYCLE_0_AND_1_MATCH_REQUEST_SENT:
                return new Cycle0And1MatchRequestSentStateController(
                        (Cycle0And1MatchRequestSentState) state,
                        injector.getInstance(HubEventLogger.class),
                        stateTransitionAction,
                        injector.getInstance(PolicyConfiguration.class),
                        new LevelOfAssuranceValidator(),
                        injector.getInstance(TransactionsConfigProxy.class),
                        injector.getInstance(ResponseFromHubFactory.class),
                        injector.getInstance(AssertionRestrictionsFactory.class),
                        injector.getInstance(MatchingServiceConfigProxy.class),
                        injector.getInstance(AttributeQueryService.class));

            case EIDAS_CYCLE_0_AND_1_MATCH_REQUEST_SENT:
                return new EidasCycle0And1MatchRequestSentStateController(
                        (EidasCycle0And1MatchRequestSentState) state,
                        stateTransitionAction,
                        injector.getInstance(HubEventLogger.class),
                        injector.getInstance(PolicyConfiguration.class),
                        new LevelOfAssuranceValidator(),
                        injector.getInstance(ResponseFromHubFactory.class),
                        injector.getInstance(AttributeQueryService.class),
                        injector.getInstance(TransactionsConfigProxy.class),
                        injector.getInstance(MatchingServiceConfigProxy.class));

            case SUCCESSFUL_MATCH:
                return new SuccessfulMatchStateController(
                        (SuccessfulMatchState) state,
                        injector.getInstance(ResponseFromHubFactory.class),
                        injector.getInstance(IdentityProvidersConfigProxy.class));

            case EIDAS_SUCCESSFUL_MATCH:
                return new EidasSuccessfulMatchStateController(
                        (EidasSuccessfulMatchState) state,
                        injector.getInstance(ResponseFromHubFactory.class),
                        injector.getInstance(CountriesService.class));

            case NON_MATCHING_JOURNEY_SUCCESS:
                return new NonMatchingJourneySuccessStateController(
                        (NonMatchingJourneySuccessState) state,
                        injector.getInstance(ResponseFromHubFactory.class));

            case NO_MATCH:
                return new NoMatchStateController(
                        (NoMatchState) state,
                        injector.getInstance(ResponseFromHubFactory.class));

            case USER_ACCOUNT_CREATED:
                return new UserAccountCreatedStateController(
                        (UserAccountCreatedState) state,
                        injector.getInstance(IdentityProvidersConfigProxy.class),
                        injector.getInstance(ResponseFromHubFactory.class));

            case AWAITING_CYCLE3_DATA:
                return new AwaitingCycle3DataStateController(
                        (AwaitingCycle3DataState) state,
                        injector.getInstance(HubEventLogger.class),
                        stateTransitionAction,
                        injector.getInstance(TransactionsConfigProxy.class),
                        injector.getInstance(ResponseFromHubFactory.class),
                        injector.getInstance(PolicyConfiguration.class),
                        injector.getInstance(AssertionRestrictionsFactory.class),
                        injector.getInstance(MatchingServiceConfigProxy.class));

            case EIDAS_AWAITING_CYCLE3_DATA:
                return new EidasAwaitingCycle3DataStateController(
                        (EidasAwaitingCycle3DataState) state,
                        injector.getInstance(HubEventLogger.class),
                        stateTransitionAction,
                        injector.getInstance(TransactionsConfigProxy.class),
                        injector.getInstance(ResponseFromHubFactory.class),
                        injector.getInstance(PolicyConfiguration.class),
                        injector.getInstance(AssertionRestrictionsFactory.class),
                        injector.getInstance(MatchingServiceConfigProxy.class));

            case CYCLE3_MATCH_REQUEST_SENT:
                return new Cycle3MatchRequestSentStateController(
                        (Cycle3MatchRequestSentState) state,
                        injector.getInstance(HubEventLogger.class),
                        stateTransitionAction,
                        injector.getInstance(PolicyConfiguration.class),
                        new LevelOfAssuranceValidator(),
                        injector.getInstance(ResponseFromHubFactory.class),
                        injector.getInstance(TransactionsConfigProxy.class),
                        injector.getInstance(MatchingServiceConfigProxy.class),
                        injector.getInstance(AssertionRestrictionsFactory.class),
                        injector.getInstance(AttributeQueryService.class));

            case EIDAS_CYCLE_3_MATCH_REQUEST_SENT:
                return new EidasCycle3MatchRequestSentStateController(
                        (EidasCycle3MatchRequestSentState) state,
                        injector.getInstance(HubEventLogger.class),
                        stateTransitionAction,
                        injector.getInstance(PolicyConfiguration.class),
                        new LevelOfAssuranceValidator(),
                        injector.getInstance(ResponseFromHubFactory.class),
                        injector.getInstance(AttributeQueryService.class),
                        injector.getInstance(TransactionsConfigProxy.class),
                        injector.getInstance(MatchingServiceConfigProxy.class));

            case TIMEOUT:
                return new TimeoutStateController(
                        (TimeoutState) state,
                        injector.getInstance(ResponseFromHubFactory.class));

            case MATCHING_SERVICE_REQUEST_ERROR:
                return new MatchingServiceRequestErrorStateController(
                        (MatchingServiceRequestErrorState) state,
                        injector.getInstance(ResponseFromHubFactory.class));

            case USER_ACCOUNT_CREATION_REQUEST_SENT:
                return new UserAccountCreationRequestSentStateController(
                        (UserAccountCreationRequestSentState) state,
                        stateTransitionAction,
                        injector.getInstance(HubEventLogger.class),
                        injector.getInstance(PolicyConfiguration.class),
                        new LevelOfAssuranceValidator(),
                        injector.getInstance(ResponseFromHubFactory.class),
                        injector.getInstance(AttributeQueryService.class),
                        injector.getInstance(TransactionsConfigProxy.class),
                        injector.getInstance(MatchingServiceConfigProxy.class));

            case EIDAS_USER_ACCOUNT_CREATION_REQUEST_SENT:
                return new EidasUserAccountCreationRequestSentStateController(
                        (EidasUserAccountCreationRequestSentState) state,
                        stateTransitionAction,
                        injector.getInstance(HubEventLogger.class),
                        injector.getInstance(PolicyConfiguration.class),
                        new LevelOfAssuranceValidator(),
                        injector.getInstance(ResponseFromHubFactory.class),
                        injector.getInstance(AttributeQueryService.class),
                        injector.getInstance(TransactionsConfigProxy.class),
                        injector.getInstance(MatchingServiceConfigProxy.class));

            case AUTHN_FAILED_ERROR:
                return new AuthnFailedErrorStateController(
                        (AuthnFailedErrorState) state,
                        injector.getInstance(ResponseFromHubFactory.class),
                        stateTransitionAction,
                        injector.getInstance(TransactionsConfigProxy.class),
                        injector.getInstance(IdentityProvidersConfigProxy.class),
                        injector.getInstance(HubEventLogger.class));

            case EIDAS_AUTHN_FAILED_ERROR:
                return new EidasAuthnFailedErrorStateController(
                        (EidasAuthnFailedErrorState) state,
                        injector.getInstance(ResponseFromHubFactory.class),
                        stateTransitionAction,
                        injector.getInstance(HubEventLogger.class));

            case FRAUD_EVENT_DETECTED:
                return new FraudEventDetectedStateController(
                        (FraudEventDetectedState) state,
                        injector.getInstance(ResponseFromHubFactory.class),
                        stateTransitionAction,
                        injector.getInstance(TransactionsConfigProxy.class),
                        injector.getInstance(IdentityProvidersConfigProxy.class),
                        injector.getInstance(HubEventLogger.class));

            case REQUESTER_ERROR:
                return new RequesterErrorStateController(
                        (RequesterErrorState) state,
                        injector.getInstance(ResponseFromHubFactory.class),
                        stateTransitionAction,
                        injector.getInstance(TransactionsConfigProxy.class),
                        injector.getInstance(IdentityProvidersConfigProxy.class),
                        injector.getInstance(HubEventLogger.class));

            case CYCLE_3_DATA_INPUT_CANCELLED:
                return new Cycle3DataInputCancelledStateController(
                        (Cycle3DataInputCancelledState) state,
                        injector.getInstance(ResponseFromHubFactory.class));

            case USER_ACCOUNT_CREATION_FAILED:
                return new UserAccountCreationFailedStateController(
                        (UserAccountCreationFailedState) state,
                        injector.getInstance(ResponseFromHubFactory.class));

            case EIDAS_USER_ACCOUNT_CREATION_FAILED:
                return new EidasUserAccountCreationFailedStateController(
                        (EidasUserAccountCreationFailedState) state,
                        injector.getInstance(ResponseFromHubFactory.class),
                        stateTransitionAction,
                        injector.getInstance(HubEventLogger.class));

            default:
                throw new IllegalStateException(format("Invalid state controller class for {0}", policyState));
        }
    }

    @Inject public  StateControllerFactory(Injector injector);

}