```swift= // MARK: - Itinerary public let ItineraryPlaceSearchConfigurationStream: PlaceSearchConfigurationStreaming { init(waypointManager: WaypointManaging) { fields = waypointManager.waypoints.enumerate().map { (index, value) in // Value var value: Place? switch value.storage { case .place(let place): value = place default: value = nil } return Field( value: value context: index == 0 ? .origin : .destination ) } focusingIndex = } } public final class ItineraryStepComponent { public var searchConfigurationStream: PlaceSearchConfigurationStreaming { shared { ItineraryPlaceSearchConfigurationStream(waypointManager: waypointManager) } } } public final class ItineraryStepRouter { func routeToPlaceSearch() { let router = placeSearchBuilder.build( listener: interactor, configuration: searchConfigurationStream ) ... } } public final class ItineraryStepInteractor: PlaceSearchListener { let configuration: PlaceSearchConfigurationStreaming // PlaceSearchListener func didSelect(result: Place) { let index = currentIndex let waypoint = Waypoint(storage: .place(place)) waypointManager.update(waypoint: waypoint, at: index) } func didSelect(coordinate: Coordinate2D) { let index = currentIndex let waypoint = Waypoint(storage: .coordinate(coordinate)) waypointManager.update(waypoint: waypoint, at: index) } } // MARK: - PlaceSearch public protocol PlaceSearchListener { func didSelect(result: Place) func didSelect(coordinate: Coordinate2D) } public protocol PlaceMapInteractorListener { func mapDidChange(location: Coordinate2D) } public protocol PlaceSearchConfigurationStreaming { public struct Field { public let value: Place? // public let isFocused: Bool public let context: LocationSearchContext } let fields: Observable<[Field]> let focusingIndex: Observable<Int> // ??? } public class PlaceSearchInteractor { let configuration: PlaceSearchConfigurationStreaming func mapDidChange(location: Coordinate2D) { listener.didSelect(coordinate: location) } } public struct PlacesSearchDependency { let waypointStream: Observable<Waypoint> } // MARK: - TextSearch public protocol TextSearchDependency { var searchConfigurationStream: PlaceSearchConfigurationStreaming { get } } public final class TextSearchComponent: Component<TextSearchDependency>{ let dynamicDependency: PlacesSearchDependency } protocol TextSearchInteractorListener: PlacesSearchListener { func didSelect(result: Place, at index: Int) // inherited // func goToViewMode(_ viewMode: ViewMode) } class TextSearchRouter { } class TextSearchInteractor { weak var listener: TextSearchInteractorListener? init(configuration: PlaceSearchConfigurationStreaming) override func didBecomeActive() { super.didBecomeActive() setupObservers() } private func setupObservers() { setupTextFieldObservers() setupResultObservers() } private func setupTextFieldObservers() { // listen to configuration and set/focus text field accordingly let fieldValues = configuration.fields.map(\.value) for index in 0..<fieldValues.count { fieldValues[index] .subscribe( onNext: { [weak self] value in self?.presenter.setFieldResult(searchResult, at: index) self?.whatsTheNextStep() // go to next empty index? } ) .disposeOnDeactivate(interactor: self) } } private func setupResultObservers() { // Observe text field change from presenter/VC and update result collection view } // View listener private func didSelect(result: Place, at index: Int) { listner?.didSelect(result: result, at: index) } } ```