2021-02-06 19:02:12 +01:00
package org.mosad.teapod.ui.activity.main.viewmodel
import android.app.Application
import androidx.lifecycle.AndroidViewModel
2021-12-28 20:32:44 +01:00
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
2021-12-31 16:03:15 +01:00
import kotlinx.serialization.ExperimentalSerializationApi
2021-12-29 19:36:33 +01:00
import org.mosad.teapod.parser.crunchyroll.*
2021-12-28 20:32:44 +01:00
import org.mosad.teapod.preferences.Preferences
2022-01-02 17:51:45 +01:00
import org.mosad.teapod.util.DataTypes.MediaType
2021-12-28 20:32:44 +01:00
import org.mosad.teapod.util.Meta
2021-12-31 16:03:15 +01:00
import org.mosad.teapod.util.tmdb.*
2021-02-06 19:02:12 +01:00
/ * *
* handle media , next ep and tmdb
2021-07-11 12:56:21 +02:00
* TODO this lives in activity , is this correct ?
2021-02-06 19:02:12 +01:00
* /
class MediaFragmentViewModel ( application : Application ) : AndroidViewModel ( application ) {
2021-12-28 20:32:44 +01:00
// var mediaCrunchy = NoneItem
// internal set
2021-12-31 16:03:15 +01:00
var seriesCrunchy = NoneSeries // movies are also series
2021-12-20 22:14:58 +01:00
internal set
var seasonsCrunchy = NoneSeasons
internal set
2021-12-29 19:36:33 +01:00
var currentSeasonCrunchy = NoneSeason
internal set
2021-12-20 22:14:58 +01:00
var episodesCrunchy = NoneEpisodes
internal set
2021-12-29 20:51:53 +01:00
val currentEpisodesCrunchy = arrayListOf < Episode > ( ) // used for EpisodeItemAdapter (easier updates)
2022-01-05 01:28:39 +01:00
var currentPlayheads : PlayheadsMap = emptyMap ( )
2022-01-02 22:39:31 +01:00
var isWatchlist = false
internal set
2021-12-20 22:14:58 +01:00
2022-01-02 22:39:31 +01:00
// TMDB stuff
2022-01-02 17:51:45 +01:00
var mediaType = MediaType . OTHER
internal set
2021-12-31 16:03:15 +01:00
var tmdbResult : TMDBResult = NoneTMDB // TODO rename
2021-02-06 19:02:12 +01:00
internal set
2021-12-31 16:03:15 +01:00
var tmdbTVSeason : TMDBTVSeason = NoneTMDBTVSeason
2021-07-11 12:56:21 +02:00
internal set
var mediaMeta : Meta ? = null
internal set
2021-02-06 19:02:12 +01:00
2021-12-28 20:32:44 +01:00
/ * *
* @param crunchyId the crunchyroll series id
* /
2021-12-20 22:14:58 +01:00
2021-12-31 16:03:15 +01:00
suspend fun loadCrunchy ( crunchyId : String ) {
2021-12-28 20:32:44 +01:00
// load series and seasons info in parallel
listOf (
viewModelScope . launch { seriesCrunchy = Crunchyroll . series ( crunchyId ) } ,
2022-01-02 22:39:31 +01:00
viewModelScope . launch { seasonsCrunchy = Crunchyroll . seasons ( crunchyId ) } ,
viewModelScope . launch { isWatchlist = Crunchyroll . isWatchlist ( crunchyId ) }
2021-12-28 20:32:44 +01:00
) . joinAll ( )
2021-12-20 22:14:58 +01:00
2021-12-28 20:32:44 +01:00
println ( " series: $seriesCrunchy " )
2021-12-27 21:14:35 +01:00
println ( " seasons: $seasonsCrunchy " )
2021-12-20 22:14:58 +01:00
2021-12-31 16:03:15 +01:00
// TODO load episodes, metaDB and tmdb in parallel
2021-12-28 20:32:44 +01:00
// load the preferred season (preferred language, language per season, not per stream)
2021-12-29 19:36:33 +01:00
currentSeasonCrunchy = seasonsCrunchy . getPreferredSeason ( Preferences . preferredLocal )
episodesCrunchy = Crunchyroll . episodes ( currentSeasonCrunchy . id )
2021-12-29 20:51:53 +01:00
currentEpisodesCrunchy . clear ( )
2021-12-29 19:36:33 +01:00
currentEpisodesCrunchy . addAll ( episodesCrunchy . items )
2021-12-27 21:14:35 +01:00
println ( " episodes: $episodesCrunchy " )
2021-12-20 22:14:58 +01:00
2022-01-05 01:28:39 +01:00
// get playheads (including fully watched state)
val episodeIDs = episodesCrunchy . items . map { it . id }
currentPlayheads = Crunchyroll . playheads ( episodeIDs )
2022-01-02 17:51:45 +01:00
// set media type
mediaType = episodesCrunchy . items . firstOrNull ( ) ?. let {
if ( it . episodeNumber != null ) MediaType . TVSHOW else MediaType . MOVIE
} ?: MediaType . OTHER
2021-12-20 22:14:58 +01:00
// TODO check if metaDB knows the title
mediaMeta = null // set mediaMeta to null, if metaDB doesn't know the media
2021-12-31 16:03:15 +01:00
// use tmdb search to get media info
loadTmdbInfo ( )
2021-12-20 22:14:58 +01:00
}
2021-02-06 19:02:12 +01:00
/ * *
2021-12-31 16:03:15 +01:00
* Load the tmdb info for the selected media .
* The TMDB search return a media type , use this to get the details ( movie / tv show and season )
2021-02-06 19:02:12 +01:00
* /
2022-01-02 22:39:31 +01:00
private suspend fun loadTmdbInfo ( ) {
2021-12-31 16:03:15 +01:00
val tmdbApiController = TMDBApiController ( )
2022-01-02 17:51:45 +01:00
val tmdbSearchResult = when ( mediaType ) {
MediaType . MOVIE -> tmdbApiController . searchMovie ( seriesCrunchy . title )
MediaType . TVSHOW -> tmdbApiController . searchTVShow ( seriesCrunchy . title )
else -> NoneTMDBSearch
}
2021-12-31 16:03:15 +01:00
println ( tmdbSearchResult )
tmdbResult = if ( tmdbSearchResult . results . isNotEmpty ( ) ) {
2022-01-02 17:51:45 +01:00
when ( val result = tmdbSearchResult . results . first ( ) ) {
is TMDBSearchResultMovie -> tmdbApiController . getMovieDetails ( result . id )
is TMDBSearchResultTVShow -> tmdbApiController . getTVShowDetails ( result . id )
2021-12-31 16:03:15 +01:00
else -> NoneTMDB
}
} else NoneTMDB
println ( tmdbResult )
// currently not used
// tmdbTVSeason = if (tmdbResult is TMDBTVShow) {
// tmdbApiController.getTVSeasonDetails(tmdbResult.id, 0)
// } else NoneTMDBTVSeason
}
2021-02-06 19:02:12 +01:00
2022-01-02 22:39:31 +01:00
/ * *
* Set currentSeasonCrunchy based on the season id . Also set the new seasons episodes .
*
* @param seasonId the id of the season to set
* /
suspend fun setCurrentSeason ( seasonId : String ) {
// return if the id hasn't changed (performance)
if ( currentSeasonCrunchy . id == seasonId ) return
// set currentSeasonCrunchy to the new season with id == seasonId, if the id isn't found,
// don't change the current season (this should/can never happen)
currentSeasonCrunchy = seasonsCrunchy . items . firstOrNull {
it . id == seasonId
} ?: currentSeasonCrunchy
episodesCrunchy = Crunchyroll . episodes ( currentSeasonCrunchy . id )
currentEpisodesCrunchy . clear ( )
currentEpisodesCrunchy . addAll ( episodesCrunchy . items )
}
suspend fun setWatchlist ( ) {
isWatchlist = if ( isWatchlist ) {
Crunchyroll . deleteWatchlist ( seriesCrunchy . id )
false
} else {
Crunchyroll . postWatchlist ( seriesCrunchy . id )
true
}
}
2021-02-06 19:02:12 +01:00
/ * *
2021-08-31 19:47:18 +02:00
* get the next episode based on episodeId
2021-02-06 19:02:12 +01:00
* if no matching is found , use first episode
* /
2021-08-31 19:47:18 +02:00
fun updateNextEpisode ( episodeId : Int ) {
2021-12-28 20:32:44 +01:00
// TODO reimplement if needed
// if (media.type == MediaType.MOVIE) return // return if movie
//
// nextEpisodeId = media.playlist.firstOrNull { it.index > media.getEpisodeById(episodeId).index }?.mediaId
// ?: media.playlist.first().mediaId
2021-02-06 19:02:12 +01:00
}
2021-12-31 16:03:15 +01:00
}