package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling import dev.inmo.micro_utils.coroutines.safelyWithoutExceptions import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTypeReceiver import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow import dev.inmo.tgbotapi.extensions.utils.* import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat import dev.inmo.tgbotapi.types.message.ChatEvents.* import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.* import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage import dev.inmo.tgbotapi.types.message.content.* import dev.inmo.tgbotapi.types.message.content.abstracts.* import dev.inmo.tgbotapi.types.message.content.media.* import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter import kotlinx.coroutines.flow.filter internal suspend inline fun BehaviourContext.onEvent( includeFilterByChatInBehaviourSubContext: Boolean = true, noinline additionalFilter: (suspend (ChatEventMessage) -> Boolean)? = null, noinline scenarioReceiver: BehaviourContextAndTypeReceiver> ) = flowsUpdatesFilter.expectFlow(bot) { it.asMessageUpdate() ?.data ?.asChatEventMessage() ?.let { message -> if (message.chatEvent is T) { val adaptedMessage = message as ChatEventMessage if (additionalFilter == null || additionalFilter(adaptedMessage)) adaptedMessage else null } else { null } }.let(::listOfNotNull) }.subscribeSafelyWithoutExceptions(scope) { triggerMessage -> val (jobToCancel, scenario) = if (includeFilterByChatInBehaviourSubContext) { val subFilter = FlowsUpdatesFilter() val subBehaviourContext = copy(flowsUpdatesFilter = subFilter) flowsUpdatesFilter.allUpdatesFlow.filter { val chat = it.sourceChat() ?: return@filter false chat.id.chatId == triggerMessage.chat.id.chatId }.subscribeSafelyWithoutExceptions(scope, subFilter.asUpdateReceiver) to subBehaviourContext } else { null to this } safelyWithoutExceptions { scenario.scenarioReceiver(triggerMessage) } jobToCancel ?.cancel() } suspend fun BehaviourContext.onChannelEvent( includeFilterByChatInBehaviourSubContext: Boolean = true, additionalFilter: (suspend (ChatEventMessage) -> Boolean)? = null, scenarioReceiver: BehaviourContextAndTypeReceiver> ) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, scenarioReceiver) suspend fun BehaviourContext.onChatEvent( includeFilterByChatInBehaviourSubContext: Boolean = true, additionalFilter: (suspend (ChatEventMessage) -> Boolean)? = null, scenarioReceiver: BehaviourContextAndTypeReceiver> ) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, scenarioReceiver) suspend fun BehaviourContext.onCommonEvent( includeFilterByChatInBehaviourSubContext: Boolean = true, additionalFilter: (suspend (ChatEventMessage) -> Boolean)? = null, scenarioReceiver: BehaviourContextAndTypeReceiver> ) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, scenarioReceiver) suspend fun BehaviourContext.onGroupEvent( includeFilterByChatInBehaviourSubContext: Boolean = true, additionalFilter: (suspend (ChatEventMessage) -> Boolean)? = null, scenarioReceiver: BehaviourContextAndTypeReceiver> ) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, scenarioReceiver) suspend fun BehaviourContext.onSupergroupEvent( includeFilterByChatInBehaviourSubContext: Boolean = true, additionalFilter: (suspend (ChatEventMessage) -> Boolean)? = null, scenarioReceiver: BehaviourContextAndTypeReceiver> ) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, scenarioReceiver) suspend fun BehaviourContext.onChannelChatCreated( includeFilterByChatInBehaviourSubContext: Boolean = true, additionalFilter: (suspend (ChatEventMessage) -> Boolean)? = null, scenarioReceiver: BehaviourContextAndTypeReceiver> ) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, scenarioReceiver) suspend fun BehaviourContext.onDeleteChatPhoto( includeFilterByChatInBehaviourSubContext: Boolean = true, additionalFilter: (suspend (ChatEventMessage) -> Boolean)? = null, scenarioReceiver: BehaviourContextAndTypeReceiver> ) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, scenarioReceiver) suspend fun BehaviourContext.onGroupChatCreated( includeFilterByChatInBehaviourSubContext: Boolean = true, additionalFilter: (suspend (ChatEventMessage) -> Boolean)? = null, scenarioReceiver: BehaviourContextAndTypeReceiver> ) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, scenarioReceiver) suspend fun BehaviourContext.onLeftChatMember( includeFilterByChatInBehaviourSubContext: Boolean = true, additionalFilter: (suspend (ChatEventMessage) -> Boolean)? = null, scenarioReceiver: BehaviourContextAndTypeReceiver> ) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, scenarioReceiver) suspend fun BehaviourContext.onNewChatMembers( includeFilterByChatInBehaviourSubContext: Boolean = true, additionalFilter: (suspend (ChatEventMessage) -> Boolean)? = null, scenarioReceiver: BehaviourContextAndTypeReceiver> ) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, scenarioReceiver) suspend fun BehaviourContext.onNewChatPhoto( includeFilterByChatInBehaviourSubContext: Boolean = true, additionalFilter: (suspend (ChatEventMessage) -> Boolean)? = null, scenarioReceiver: BehaviourContextAndTypeReceiver> ) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, scenarioReceiver) suspend fun BehaviourContext.onNewChatTitle( includeFilterByChatInBehaviourSubContext: Boolean = true, additionalFilter: (suspend (ChatEventMessage) -> Boolean)? = null, scenarioReceiver: BehaviourContextAndTypeReceiver> ) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, scenarioReceiver) suspend fun BehaviourContext.onPinnedMessage( includeFilterByChatInBehaviourSubContext: Boolean = true, additionalFilter: (suspend (ChatEventMessage) -> Boolean)? = null, scenarioReceiver: BehaviourContextAndTypeReceiver> ) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, scenarioReceiver) suspend fun BehaviourContext.onProximityAlertTriggered( includeFilterByChatInBehaviourSubContext: Boolean = true, additionalFilter: (suspend (ChatEventMessage) -> Boolean)? = null, scenarioReceiver: BehaviourContextAndTypeReceiver> ) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, scenarioReceiver) suspend fun BehaviourContext.onSupergroupChatCreated( includeFilterByChatInBehaviourSubContext: Boolean = true, additionalFilter: (suspend (ChatEventMessage) -> Boolean)? = null, scenarioReceiver: BehaviourContextAndTypeReceiver> ) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, scenarioReceiver)