package eventDemo.testHelpers import eventDemo.contexts.auth.domain.User import eventDemo.contexts.game.application.command.models.GameCommand import eventDemo.contexts.game.application.command.models.JoinTheGameCommand import eventDemo.contexts.game.application.command.models.PlayCardCommand import eventDemo.contexts.game.application.command.models.ReadyToPlayCommand import eventDemo.contexts.game.application.eventStores.GameRepository import eventDemo.contexts.game.domain.game.Card import eventDemo.contexts.game.domain.game.GameId import eventDemo.contexts.game.domain.game.Player import eventDemo.contexts.game.domain.game.gameState.Game import kotlinx.coroutines.channels.Channel import org.koin.core.Koin object CreateGameWithCommandsInChannelsHelpers { class Data( private val repo: GameRepository, val gameId: GameId, val currentUser: User, ) { fun getPlayer(user: User): Player = game.players.get(user.id) val currentPlayer: Player get() = getPlayer(currentUser) val game: Game get() = repo.get(gameId)!! } context(koin: Koin) suspend fun createGameWithCommandsInChannels( channelCommand: Channel, gameId: GameId, user: User, block: suspend context( CreateGameWithCommandsInChannelsHelpers, Channel, User, ) Data.() -> T, ): T { val repo = koin.get() repo.getOrCreate(gameId) return with(channelCommand) { with(user) { with(CreateGameWithCommandsInChannelsHelpers) { Data(repo, gameId, user).block() } } } } context(channelCommand: Channel, data: Data) suspend fun joinTheGame(): JoinTheGameCommand = JoinTheGameCommand( data.currentUser.id, JoinTheGameCommand.Payload(data.gameId), ).also { channelCommand.send(it) } context(channelCommand: Channel, data: Data) suspend fun readyToPlay(): ReadyToPlayCommand = ReadyToPlayCommand( data.currentUser.id, ReadyToPlayCommand.Payload(data.gameId, data.currentPlayer.id), ).also { channelCommand.send(it) } context(channelCommand: Channel, data: Data) suspend fun playCard( card: Card, chosenColor: Card.Color? = null, ): PlayCardCommand = PlayCardCommand( data.currentUser.id, PlayCardCommand.Payload(data.gameId, data.currentPlayer.id, card, chosenColor), ).also { channelCommand.send(it) } }