package fr.dbsoft.swapcardtest.artistbrowser.ui
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import fr.dbsoft.swapcardtest.artistbrowser.data.model.*
import fr.dbsoft.swapcardtest.artistbrowser.data.repository.ArtistRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import timber.log.Timber
class ArtistBrowserViewModel(val repository: ArtistRepository) : ViewModel() {
private val coroutineScope = CoroutineScope(Dispatchers.Main)
// Search
val fetchedArtistsLiveData = MutableLiveData<List<BasicArtist>>()
private var fetchedArtists = mutableListOf<BasicArtist>()
var editTextErrorMessage = MutableLiveData<String>()
var showErrorLiveData = MutableLiveData<Unit>()
var lastHandledErrorMessage = ""
var totalSearchCount = 0
private var pageInfo = PageInfo()
private var searchText = ""
//Bookmark
var readyForDataTracking = MutableLiveData<Boolean>()
var bookmarkedArtistsLiveData: LiveData<List<BasicArtist>>? = null
var bookmarkedArtistsHashSetLiveData = MutableLiveData<HashSet<String>>()
var bookmarkedArtistsHashSet = HashSet<String>()
//Details
var artistLiveData = MutableLiveData<Artist>()
var artist: Artist? = null
var isLoadingData = MutableLiveData<Boolean>()
// region Search
fun search(searchText: String) = coroutineScope.launch {
Timber.d("search(searchText = $searchText)")
try {
isLoadingData.value = true
this@ArtistBrowserViewModel.searchText = searchText
val result = repository.searchArtistsFor(searchText)
resetSearchResult()
when (result) {
is Response.Success -> updateResult(result.value)
is Response.Error -> onError(result)
}
isLoadingData.value = false
} catch (e: IllegalArgumentException) {
isLoadingData.value = false
editTextErrorMessage.value = e.message
}
}
fun fetchMoreResult() = coroutineScope.launch {
Timber.d("fetchMoreResult for=${this@ArtistBrowserViewModel.searchText} after=${pageInfo.endCursor}")
if (isLoadingData.value == false && pageInfo.hasNextPage && this@ArtistBrowserViewModel.searchText.isNotBlank()) {
isLoadingData.value = true
val result =
repository.fetchMoreResultFor(
this@ArtistBrowserViewModel.searchText,
pageInfo.endCursor
)
when (result) {
is Response.Success -> updateResult(result.value)
is Response.Error -> onError(result)
}
isLoadingData.value = false
}
}
private fun resetSearchResult() {
fetchedArtists.clear()
}
private fun updateResult(result: SearchFetchResult?) {
result?.let {
totalSearchCount = result.totalCount
pageInfo = result.pageInfo
fetchedArtists.addAll(result.artists)
}
fetchedArtistsLiveData.value = fetchedArtists
}
private fun onError(error: Response.Error) {
var errorMessage = error.throwable?.message
errorMessage += error.throwable?.cause?.message?.let { ". Caused by: $it" }
errorMessage?.let {
lastHandledErrorMessage = errorMessage
showErrorLiveData.value = Unit
}
}
// endregion
// region Bookmark
fun onBookmarkViewCreated() {
getBookMarks()
}
private fun getBookMarks() = coroutineScope.launch {
bookmarkedArtistsLiveData = repository.getBookMarks()
readyForDataTracking.value = true
}
fun onBookmarksUpdated() {
val bookmarkedArtists = bookmarkedArtistsLiveData?.value
bookmarkedArtistsHashSet.clear()
bookmarkedArtists?.forEach {
bookmarkedArtistsHashSet.add(it.id)
}
bookmarkedArtistsHashSetLiveData.value = bookmarkedArtistsHashSet
}
// endregion
// region Artist Detail
fun onDetailsViewOpened(artistId: String) {
getDetailsFor(artistId)
}
private fun getDetailsFor(artistId: String) = coroutineScope.launch {
isLoadingData.value = true
when (val result = repository.getArtistFor(artistId)) {
is Response.Success -> updateArtistDetails(result.value)
is Response.Error -> onError(result)
}
isLoadingData.value = false
}
private fun updateArtistDetails(result: Artist?) {
artist = result
artist?.isBookmarked = bookmarkedArtistsHashSet.contains(result?.id)
artistLiveData.value = artist
}
fun detailBookMarkButtonClickedFor(artist: BasicArtist) = coroutineScope.launch {
bookmarkButtonClickedFor(artist)
this@ArtistBrowserViewModel.artist?.isBookmarked = !artist.isBookmarked
artistLiveData.value = this@ArtistBrowserViewModel.artist
}
// endregion
fun bookmarkButtonClickedFor(artist: BasicArtist) = coroutineScope.launch {
val artistIndex = fetchedArtists.indexOf(artist)
artist.isBookmarked = !artist.isBookmarked
if (artist.isBookmarked) {
repository.bookmark(artist)
} else {
repository.unBookMark(artist)
}
if (artistIndex != -1) {
fetchedArtists[artistIndex] = artist
fetchedArtistsLiveData.value = fetchedArtists
}
}
override fun onCleared() {
super.onCleared()
repository.stopRequests()
}
}