<commit_before>package chat.rocket.android.chatroom.presentation

import android.net.Uri
import chat.rocket.android.R
import chat.rocket.android.chatroom.adapter.AutoCompleteType
import chat.rocket.android.chatroom.adapter.PEOPLE
import chat.rocket.android.chatroom.adapter.ROOMS
import chat.rocket.android.chatroom.domain.UriInteractor
import chat.rocket.android.chatroom.viewmodel.BaseViewModel
import chat.rocket.android.chatroom.viewmodel.MessageViewModel
import chat.rocket.android.chatroom.viewmodel.ViewModelMapper
import chat.rocket.android.chatroom.viewmodel.suggestion.ChatRoomSuggestionViewModel
import chat.rocket.android.chatroom.viewmodel.suggestion.CommandSuggestionViewModel
import chat.rocket.android.chatroom.viewmodel.suggestion.PeopleSuggestionViewModel
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.infrastructure.username
import chat.rocket.android.server.domain.*
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import chat.rocket.android.server.infraestructure.state
import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.launchUI
import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatException
import chat.rocket.common.model.RoomType
import chat.rocket.common.model.SimpleUser
import chat.rocket.common.model.UserStatus
import chat.rocket.common.model.roomTypeOf
import chat.rocket.common.util.ifNull
import chat.rocket.core.internal.realtime.State
import chat.rocket.core.internal.rest.*
import chat.rocket.core.model.Command
import chat.rocket.core.model.Message
import chat.rocket.core.model.Myself
import chat.rocket.core.model.Value
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.async
import kotlinx.coroutines.experimental.channels.Channel
import kotlinx.coroutines.experimental.launch
import org.threeten.bp.Instant
import timber.log.Timber
import java.util.*
import javax.inject.Inject

class ChatRoomPresenter @Inject constructor(private val view: ChatRoomView,
                                            private val navigator: ChatRoomNavigator,
                                            private val strategy: CancelStrategy,
                                            getSettingsInteractor: GetSettingsInteractor,
                                            serverInteractor: GetCurrentServerInteractor,
                                            private val getChatRoomsInteractor: GetChatRoomsInteractor,
                                            private val permissions: GetPermissionsInteractor,
                                            private val uriInteractor: UriInteractor,
                                            private val messagesRepository: MessagesRepository,
                                            private val usersRepository: UsersRepository,
                                            private val roomsRepository: RoomRepository,
                                            private val localRepository: LocalRepository,
                                            factory: ConnectionManagerFactory,
                                            private val mapper: ViewModelMapper,
                                            private val jobSchedulerInteractor: JobSchedulerInteractor) {
    private val currentServer = serverInteractor.get()!!
    private val manager = factory.create(currentServer)
    private val client = manager.client
    private var settings: Map<String, Value<Any>> = getSettingsInteractor.get(serverInteractor.get()!!)
    private val messagesChannel = Channel<Message>()

    private var chatRoomId: String? = null
    private var chatRoomType: String? = null
    private val stateChannel = Channel<State>()
    private var lastState = manager.state

    fun loadMessages(chatRoomId: String, chatRoomType: String, offset: Long = 0) {
        this.chatRoomId = chatRoomId
        this.chatRoomType = chatRoomType
        launchUI(strategy) {
            view.showLoading()
            try {
                val localMessages = messagesRepository.getByRoomId(chatRoomId)
                val oldMessages = mapper.map(localMessages)
                view.showMessages(oldMessages)
                if (oldMessages.isEmpty()) {
                    val messages =
                        retryIO(description = "messages chatRoom: $chatRoomId, type: $chatRoomType, offset: $offset") {
                            client.messages(chatRoomId, roomTypeOf(chatRoomType), offset, 30).result
                        }
                    messagesRepository.saveAll(messages)
                    val allMessages = mapper.map(messages)
                    view.showMessages(allMessages)
                } else {
                    loadMissingMessages()
                }

                // TODO: For now we are marking the room as read if we can get the messages (I mean, no exception occurs)
                // but should mark only when the user see the first unread message.
                markRoomAsRead(chatRoomId)

                subscribeMessages(chatRoomId)
            } catch (ex: Exception) {
                Timber.e(ex)
                ex.message?.let {
                    view.showMessage(it)
                }.ifNull {
                    view.showGenericErrorMessage()
                }
            } finally {
                view.hideLoading()
            }

            if (offset == 0L) {
                subscribeState()
            }
        }
    }

    fun sendMessage(chatRoomId: String, text: String, messageId: String?) {
        launchUI(strategy) {
            try {
                // ignore message for now, will receive it on the stream
                val id = UUID.randomUUID().toString()
                val message = if (messageId == null) {
                    val username = localRepository.username()
                    val newMessage = Message(
                        id = id,
                        roomId = chatRoomId,
                        message = text,
                        timestamp = Instant.now().toEpochMilli(),
                        sender = SimpleUser(null, username, username),
                        attachments = null,
                        avatar = currentServer.avatarUrl(username!!),
                        channels = null,
                        editedAt = null,<commit_msg>Fix loading same page always on chat<commit_after>package chat.rocket.android.chatroom.presentation

import android.net.Uri
import chat.rocket.android.R
import chat.rocket.android.chatroom.adapter.AutoCompleteType
import chat.rocket.android.chatroom.adapter.PEOPLE
import chat.rocket.android.chatroom.adapter.ROOMS
import chat.rocket.android.chatroom.domain.UriInteractor
import chat.rocket.android.chatroom.viewmodel.ViewModelMapper
import chat.rocket.android.chatroom.viewmodel.suggestion.ChatRoomSuggestionViewModel
import chat.rocket.android.chatroom.viewmodel.suggestion.CommandSuggestionViewModel
import chat.rocket.android.chatroom.viewmodel.suggestion.PeopleSuggestionViewModel
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.infrastructure.username
import chat.rocket.android.server.domain.*
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import chat.rocket.android.server.infraestructure.state
import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.launchUI
import chat.rocket.android.util.retryIO
import chat.rocket.common.RocketChatException
import chat.rocket.common.model.RoomType
import chat.rocket.common.model.SimpleUser
import chat.rocket.common.model.UserStatus
import chat.rocket.common.model.roomTypeOf
import chat.rocket.common.util.ifNull
import chat.rocket.core.internal.realtime.State
import chat.rocket.core.internal.rest.*
import chat.rocket.core.model.Command
import chat.rocket.core.model.Message
import chat.rocket.core.model.Myself
import chat.rocket.core.model.Value
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.async
import kotlinx.coroutines.experimental.channels.Channel
import kotlinx.coroutines.experimental.launch
import org.threeten.bp.Instant
import timber.log.Timber
import java.util.*
import javax.inject.Inject

class ChatRoomPresenter @Inject constructor(private val view: ChatRoomView,
                                            private val navigator: ChatRoomNavigator,
                                            private val strategy: CancelStrategy,
                                            getSettingsInteractor: GetSettingsInteractor,
                                            serverInteractor: GetCurrentServerInteractor,
                                            private val getChatRoomsInteractor: GetChatRoomsInteractor,
                                            private val permissions: GetPermissionsInteractor,
                                            private val uriInteractor: UriInteractor,
                                            private val messagesRepository: MessagesRepository,
                                            private val usersRepository: UsersRepository,
                                            private val roomsRepository: RoomRepository,
                                            private val localRepository: LocalRepository,
                                            factory: ConnectionManagerFactory,
                                            private val mapper: ViewModelMapper,
                                            private val jobSchedulerInteractor: JobSchedulerInteractor) {
    private val currentServer = serverInteractor.get()!!
    private val manager = factory.create(currentServer)
    private val client = manager.client
    private var settings: Map<String, Value<Any>> = getSettingsInteractor.get(serverInteractor.get()!!)
    private val messagesChannel = Channel<Message>()

    private var chatRoomId: String? = null
    private var chatRoomType: String? = null
    private val stateChannel = Channel<State>()
    private var lastState = manager.state

    fun loadMessages(chatRoomId: String, chatRoomType: String, offset: Long = 0) {
        this.chatRoomId = chatRoomId
        this.chatRoomType = chatRoomType
        launchUI(strategy) {
            view.showLoading()
            try {
                if (offset == 0L) {
                    val localMessages = messagesRepository.getByRoomId(chatRoomId)
                    val oldMessages = mapper.map(localMessages)
                    if (oldMessages.isNotEmpty()) {
                        view.showMessages(oldMessages)
                        loadMissingMessages()
                    } else {
                        loadAndShowMessages(chatRoomId, chatRoomType, offset)
                    }
                } else {
                    loadAndShowMessages(chatRoomId, chatRoomType, offset)
                }

                // TODO: For now we are marking the room as read if we can get the messages (I mean, no exception occurs)
                // but should mark only when the user see the first unread message.
                markRoomAsRead(chatRoomId)

                subscribeMessages(chatRoomId)
            } catch (ex: Exception) {
                Timber.e(ex)
                ex.message?.let {
                    view.showMessage(it)
                }.ifNull {
                    view.showGenericErrorMessage()
                }
            } finally {
                view.hideLoading()
            }

            if (offset == 0L) {
                subscribeState()
            }
        }
    }

    private suspend fun loadAndShowMessages(chatRoomId: String, chatRoomType: String, offset: Long = 0) {
        val messages =
            retryIO(description = "messages chatRoom: $chatRoomId, type: $chatRoomType, offset: $offset") {
                client.messages(chatRoomId, roomTypeOf(chatRoomType), offset, 30).result
            }
        messagesRepository.saveAll(messages)
        val allMessages = mapper.map(messages)
        view.showMessages(allMessages)
    }

    fun sendMessage(chatRoomId: String, text: String, messageId: String?) {
        launchUI(strategy) {
            try {
                // ignore message for now, will receive it on the stream
                val id = UUID.randomUUID().toString()
                val message = if (messageId == null) {
                    val username = localRepository.username()
                    val newMessage = Message(
                        id = id,
                        roomId = chatRoomId,
                        message = text,
                        timestamp = Instant.now().toEpochMilli(),
                        sender = SimpleUser(null, username, username),
                        attachments = null,
                        avatar = currentServer.avatarUrl(username!!),
                        channels = null,
                        editedAt = null,
{'fraction_non_alphanumeric': 0.07063450049156772, 'fraction_numerical': 0.0007562580352416244, 'mean_word_length': 1.9703504043126685, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 56, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1376738', 'n_tokens_mistral': 3171, 'n_tokens_neox': 3019, 'n_words': 681}