package org.mosad.teapod.util.adapter import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.graphics.drawable.Drawable import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import com.bumptech.glide.request.RequestOptions import jp.wasabeef.glide.transformations.RoundedCornersTransformation import org.mosad.teapod.R import org.mosad.teapod.databinding.ItemEpisodeBinding import org.mosad.teapod.databinding.ItemEpisodePlayerBinding import org.mosad.teapod.parser.crunchyroll.Episode import org.mosad.teapod.parser.crunchyroll.PlayheadObject import org.mosad.teapod.parser.crunchyroll.PlayheadsMap import org.mosad.teapod.util.tmdb.TMDBTVEpisode class EpisodeItemAdapter( private val episodes: List, private val tmdbEpisodes: List?, private val playheads: PlayheadsMap, private val onClickListener: OnClickListener, private val viewType: ViewType ) : RecyclerView.Adapter() { var currentSelected: Int = -1 // -1, since position should never be < 0 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return when (viewType) { ViewType.PLAYER.ordinal -> { PlayerEpisodeViewHolder((ItemEpisodePlayerBinding.inflate(LayoutInflater.from(parent.context), parent, false))) } else -> { // media fragment episode list is default EpisodeViewHolder(ItemEpisodeBinding.inflate(LayoutInflater.from(parent.context), parent, false)) } } } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { val episode = episodes[position] val playhead = playheads[episode.id] val tmdbEpisode = tmdbEpisodes?.getOrNull(position) when (holder.itemViewType) { ViewType.MEDIA_FRAGMENT.ordinal -> { (holder as EpisodeViewHolder).bind(episode, playhead, tmdbEpisode) } ViewType.PLAYER.ordinal -> { (holder as PlayerEpisodeViewHolder).bind(episode, playhead, currentSelected) } } } override fun getItemViewType(position: Int): Int { return when (viewType) { ViewType.MEDIA_FRAGMENT -> ViewType.MEDIA_FRAGMENT.ordinal ViewType.PLAYER -> ViewType.PLAYER.ordinal } } override fun getItemCount(): Int { return episodes.size } inner class EpisodeViewHolder(val binding: ItemEpisodeBinding) : RecyclerView.ViewHolder(binding.root) { fun bind(episode: Episode, playhead: PlayheadObject?, tmdbEpisode: TMDBTVEpisode?) { val context = binding.root.context val titleText = if (episode.episodeNumber != null) { // for tv shows add ep prefix and episode number if (episode.isDubbed) { context.getString(R.string.component_episode_title, episode.episode, episode.title) } else { context.getString(R.string.component_episode_title_sub, episode.episode, episode.title) } } else { episode.title } binding.textEpisodeTitle.text = titleText binding.textEpisodeDesc.text = episode.description.ifEmpty { tmdbEpisode?.overview ?: "" } if (episode.images.thumbnail[0][0].source.isNotEmpty()) { Glide.with(context).load(episode.images.thumbnail[0][0].source) .apply(RequestOptions.placeholderOf(ColorDrawable(Color.DKGRAY))) .apply(RequestOptions.bitmapTransform(RoundedCornersTransformation(10, 0))) .into(binding.imageEpisode) } // add watched progress val playheadProgress = playhead?.playhead?.let { ((it.toFloat() / (episode.durationMs / 1000)) * 100).toInt() } ?: 0 binding.progressPlayhead.setProgressCompat(playheadProgress, false) binding.progressPlayhead.visibility = if (playheadProgress <= 0) View.GONE else View.VISIBLE // add watched icon to episode, if the episode id is present in playheads and fullyWatched val watchedImage: Drawable? = if (playhead?.fullyWatched == true) { ContextCompat.getDrawable(context, R.drawable.ic_baseline_check_circle_24) } else { null } binding.imageWatched.setImageDrawable(watchedImage) binding.imageEpisode.setOnClickListener { onClickListener.onClick(episode) } } } inner class PlayerEpisodeViewHolder(val binding: ItemEpisodePlayerBinding) : RecyclerView.ViewHolder(binding.root) { // -1, since position should never be < 0 fun bind(episode: Episode, playhead: PlayheadObject?, currentSelected: Int) { val context = binding.root.context val titleText = if (episode.episodeNumber != null) { // for tv shows add ep prefix and episode number if (episode.isDubbed) { context.getString(R.string.component_episode_title, episode.episode, episode.title) } else { context.getString(R.string.component_episode_title_sub, episode.episode, episode.title) } } else { episode.title } binding.textEpisodeTitle2.text = titleText binding.textEpisodeDesc2.text = episode.description.ifEmpty { "" } if (episode.images.thumbnail[0][0].source.isNotEmpty()) { Glide.with(context).load(episode.images.thumbnail[0][0].source) .apply(RequestOptions.bitmapTransform(RoundedCornersTransformation(10, 0))) .into(binding.imageEpisode) } // add watched progress val playheadProgress = playhead?.playhead?.let { ((it.toFloat() / (episode.durationMs / 1000)) * 100).toInt() } ?: 0 binding.progressPlayhead.setProgressCompat(playheadProgress, false) binding.progressPlayhead.visibility = if (playheadProgress <= 0) View.GONE else View.VISIBLE // hide the play icon, if it's the current episode binding.imageEpisodePlay.visibility = if (currentSelected == bindingAdapterPosition) { View.GONE } else { View.VISIBLE } if (currentSelected != bindingAdapterPosition) { binding.imageEpisode.setOnClickListener { onClickListener.onClick(episode) } } } } class OnClickListener(val clickListener: (episode: Episode) -> Unit) { fun onClick(episode: Episode) = clickListener(episode) } enum class ViewType { MEDIA_FRAGMENT, PLAYER } }