MovieRemoteDataSource.kt
package com.louisfn.somovie.data.network.datasource
import androidx.annotation.AnyThread
import com.louisfn.somovie.data.network.ApiServiceExecutor
import com.louisfn.somovie.data.network.HttpException
import com.louisfn.somovie.data.network.StatusCode.RESOURCE_REQUESTED_NOT_FOUND
import com.louisfn.somovie.data.network.response.MovieAccountStateResponse
import com.louisfn.somovie.data.network.response.MovieDetailsResponse
import com.louisfn.somovie.data.network.response.MovieResponse
import com.louisfn.somovie.data.network.response.PaginatedResultsResponse
import com.louisfn.somovie.domain.exception.MovieNotFoundException
import com.louisfn.somovie.domain.model.ExploreCategory
import javax.inject.Inject
interface MovieRemoteDataSource {
@AnyThread
suspend fun getMovies(
category: ExploreCategory,
page: Int,
): PaginatedResultsResponse<MovieResponse>
@AnyThread
suspend fun getPopular(page: Int): PaginatedResultsResponse<MovieResponse>
@AnyThread
suspend fun getNowPlaying(page: Int): PaginatedResultsResponse<MovieResponse>
@AnyThread
suspend fun getTopRated(page: Int): PaginatedResultsResponse<MovieResponse>
@AnyThread
suspend fun getUpcoming(page: Int): PaginatedResultsResponse<MovieResponse>
@AnyThread
suspend fun getMovieDetails(movieId: Long): MovieDetailsResponse
@AnyThread
suspend fun getMovieAccountStates(movieId: Long): MovieAccountStateResponse
}
internal class DefaultMovieRemoteDataSource @Inject constructor(
private val executor: ApiServiceExecutor,
) : MovieRemoteDataSource {
override suspend fun getMovies(
category: ExploreCategory,
page: Int,
): PaginatedResultsResponse<MovieResponse> =
when (category) {
ExploreCategory.UPCOMING -> getUpcoming(page)
ExploreCategory.NOW_PLAYING -> getNowPlaying(page)
ExploreCategory.TOP_RATED -> getTopRated(page)
ExploreCategory.POPULAR -> getPopular(page)
}
override suspend fun getPopular(page: Int): PaginatedResultsResponse<MovieResponse> =
executor.execute {
it.getPopularMovies(page)
}
override suspend fun getNowPlaying(page: Int): PaginatedResultsResponse<MovieResponse> =
executor.execute {
it.getNowPlayingMovies(page)
}
override suspend fun getTopRated(page: Int): PaginatedResultsResponse<MovieResponse> =
executor.execute {
it.getTopRatedMovies(page)
}
override suspend fun getUpcoming(page: Int): PaginatedResultsResponse<MovieResponse> =
executor.execute {
it.getUpcomingMovies(page)
}
override suspend fun getMovieDetails(movieId: Long): MovieDetailsResponse =
executor.execute(mapHttpException = ::mapHttpException) {
it.getMovieDetails(movieId)
}
override suspend fun getMovieAccountStates(movieId: Long): MovieAccountStateResponse =
executor.execute(mapHttpException = ::mapHttpException) {
it.getMovieAccountStates(movieId)
}
@AnyThread
private fun mapHttpException(e: HttpException) =
when (e.statusCode) {
RESOURCE_REQUESTED_NOT_FOUND -> MovieNotFoundException()
else -> null
}
}