package org.mosad.teapod.ui.activity.main.fragments

import android.annotation.SuppressLint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.PopupMenu
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
import org.mosad.teapod.R
import org.mosad.teapod.databinding.FragmentMediaEpisodesBinding
import org.mosad.teapod.ui.activity.main.viewmodel.MediaFragmentViewModel
import org.mosad.teapod.util.adapter.EpisodeItemAdapter

class MediaFragmentEpisodes : Fragment() {

    private lateinit var binding: FragmentMediaEpisodesBinding
    private lateinit var adapterRecEpisodes: EpisodeItemAdapter

    private val model: MediaFragmentViewModel by viewModels({requireParentFragment()})

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        binding = FragmentMediaEpisodesBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        adapterRecEpisodes = EpisodeItemAdapter(
            model.currentEpisodesCrunchy,
            model.tmdbTVSeason.episodes,
            model.currentPlayheads,
            EpisodeItemAdapter.OnClickListener { episode ->
                (requireParentFragment() as? MediaFragment)?.playEpisode(episode.seasonId, episode.id)
            },
            EpisodeItemAdapter.ViewType.MEDIA_FRAGMENT
        )
        binding.recyclerEpisodes.adapter = adapterRecEpisodes

        // don't show season selection if only one season is present
        if (model.seasonsCrunchy.total < 2) {
            binding.buttonSeasonSelection.visibility = View.GONE
        } else {
            binding.buttonSeasonSelection.text = getString(
                R.string.season_number_title,
                model.currentSeasonCrunchy.seasonNumber,
                model.currentSeasonCrunchy.title
            )
            binding.buttonSeasonSelection.setOnClickListener { v ->
                showSeasonSelection(v)
            }
        }
    }

    @SuppressLint("NotifyDataSetChanged")
    fun updateWatchedState() {
        // model.currentPlayheads is a val mutable map -> notify dataset changed
        if (this::adapterRecEpisodes.isInitialized) {
            adapterRecEpisodes.notifyDataSetChanged()
        }
    }

    private fun showSeasonSelection(v: View) {
        // TODO replace with Exposed dropdown menu: https://material.io/components/menus/android#exposed-dropdown-menus
        val popup = PopupMenu(requireContext(), v)
        model.seasonsCrunchy.data.forEach { season ->
            popup.menu.add(getString(
                    R.string.season_number_title,
                    season.seasonNumber,
                    season.title
                )
            ).also {
                it.setOnMenuItemClickListener {
                    onSeasonSelected(season.id)
                    false
                }
            }
        }

        popup.show()
    }

    /**
     * Call model to load a new season.
     * Once loaded update buttonSeasonSelection text and adapterRecEpisodes.
     *
     * Suppress waring since invalid.
     */
    @SuppressLint("NotifyDataSetChanged")
    private fun onSeasonSelected(seasonId: String) {
        // load the new season
        lifecycleScope.launch {
            model.setCurrentSeason(seasonId)
            binding.buttonSeasonSelection.text = getString(
                R.string.season_number_title,
                model.currentSeasonCrunchy.seasonNumber,
                model.currentSeasonCrunchy.title
            )
            adapterRecEpisodes.notifyDataSetChanged()
        }
    }

}