package melody.offline.music.activity

import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.view.View
import android.view.animation.AnimationUtils
import android.widget.Toast
import androidx.annotation.OptIn
import androidx.core.net.toUri
import androidx.media3.common.MediaItem
import androidx.media3.common.PlaybackException
import androidx.media3.common.Player
import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.offline.Download
import androidx.media3.exoplayer.offline.DownloadRequest
import androidx.media3.exoplayer.offline.DownloadService
import androidx.recyclerview.widget.LinearLayoutManager
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.gyf.immersionbar.ktx.immersionBar
import melody.offline.music.R
import melody.offline.music.adapter.DetailsPlayListAdapter
import melody.offline.music.databinding.ActivityMoPlayDetailsBinding
import melody.offline.music.innertube.Innertube
import melody.offline.music.media.MediaControllerManager
import melody.offline.music.media.SongRadio
import melody.offline.music.service.MyDownloadService
import melody.offline.music.service.ViewModelMain
import melody.offline.music.sp.AppStore
import melody.offline.music.util.DownloadUtil
import melody.offline.music.util.LogTag.LogD
import melody.offline.music.util.PlayMode
import melody.offline.music.util.asMediaItem
import melody.offline.music.util.convertMillisToMinutesAndSecondsString
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.selects.select
import org.json.JSONObject
import melody.offline.music.App
import melody.offline.music.ads.AdPlacement
import melody.offline.music.ads.LolAdWrapper
import melody.offline.music.util.AnalysisUtil

@OptIn(UnstableApi::class)
class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {

    private val requests: Channel<Request> = Channel(Channel.UNLIMITED)

    sealed class Request {
        data object OnFavorites : Request()
        data class OnDownload(val mediaItem: MediaItem) : Request()
        data class UpdateFavorite(val id: String) : Request()
    }


    companion object {
        const val PLAY_DETAILS_VIDEO_ID = "play_details_videoId"
        const val PLAY_DETAILS_PLAY_LIST_ID = "play_details_playlistId"
        const val PLAY_DETAILS_PLAY_LIST_SET_VIDEO_ID = "play_details_play_list_set_video_id"
        const val PLAY_DETAILS_PLAY_PARAMS = "play_details_play_params"
        const val PLAY_DETAILS_NAME = "play_details_name"
        const val PLAY_DETAILS_DESC = "play_details_desc"
        const val PLAY_DETAILS_COME_FROM = "PLAY_DETAILS_COME_FROM"
    }

    private lateinit var binding: ActivityMoPlayDetailsBinding

    private var currentVideoID = ""

    private var comeFrom: Class<*>? = null
    private var detailsPlayListAdapter: DetailsPlayListAdapter? = null

    private var startPlayTime = 0L

    private fun initImmersionBar() {
        immersionBar {
            statusBarDarkFont(false)
            statusBarView(binding.view)
        }
    }

    override suspend fun main() {
        binding = ActivityMoPlayDetailsBinding.inflate(layoutInflater)
        setContentView(binding.root)
        AnalysisUtil.logEvent(AnalysisUtil.PLAYER_B_PV)
        showAD()
        initImmersionBar()
        initClick()
        initPlayerListener()
        initPlayListAdapter()
        updatePlayModeUi()
        val videoId = intent.getStringExtra(PLAY_DETAILS_VIDEO_ID)
        val playlistId = intent.getStringExtra(PLAY_DETAILS_PLAY_LIST_ID)
        val playlistSetVideoId = intent.getStringExtra(PLAY_DETAILS_PLAY_LIST_SET_VIDEO_ID)
        val params = intent.getStringExtra(PLAY_DETAILS_PLAY_PARAMS)

        comeFrom = intent.getSerializableExtra(PLAY_DETAILS_COME_FROM) as Class<*>?
        if (comeFrom != null && comeFrom == PrimaryActivity::class.java) {
            LogD(TAG, "从当前播放的悬浮layout进入")
            // 处理来自 PrimaryActivity 的情况
            updateCurrentMediaItemInfo()
            if (meController != null && meController.currentMediaItem != null) {
                updateInfoUi(meController.currentMediaItem)
            }
        } else if (comeFrom != null && comeFrom == MoOfflineSongsActivity::class.java) {
            LogD(TAG, "从offline songs 进入")
            binding.nameTv.text = intent.getStringExtra(PLAY_DETAILS_NAME)
            binding.descTv.text = intent.getStringExtra(PLAY_DETAILS_DESC)
            //从数据库获取所有的offline
            val offlineBeans = App.appOfflineDBManager.getAllOfflineBeans()
            //过滤只有大小大于0的才添加到集合中
            val allFilteredBeans =
                offlineBeans.filter { it.bytesDownloaded?.let { bytes -> bytes > 0 } == true }
            //找到当前点击进来的歌曲media
            val findCurrentMedia = allFilteredBeans.find { it.videoId == videoId }?.asMediaItem
            if (findCurrentMedia != null) {
                binding.likeAndDownloadLayout.visibility = View.VISIBLE
                updateInfoUi(findCurrentMedia)
                binding.playbackErrorLayout.visibility = View.GONE
                binding.totalDurationTv.visibility = View.GONE
                meController?.let {
                    it.setMediaItem(findCurrentMedia, true)
                    it.prepare()
                    it.play()
                    val mediaItems =
                        allFilteredBeans.map { mapAll -> mapAll.asMediaItem }//转换成MediaItem
                            .filter { filter -> filter.mediaId != videoId }//过滤掉id相等的。
                    it.addMediaItems(mediaItems)
                }
                updatePlayListDataAndAdapter()
            } else {
                binding.playbackErrorLayout.visibility = View.VISIBLE
            }
        } else if (comeFrom != null && comeFrom == MoLikedSongsActivity::class.java) {
            LogD(TAG, "从liked songs 进入")
            binding.nameTv.text = intent.getStringExtra(PLAY_DETAILS_NAME)
            binding.descTv.text = intent.getStringExtra(PLAY_DETAILS_DESC)
            val favoriteBeans = App.appFavoriteDBManager.getAllFavoriteBeans()
            val allFilteredBeans = favoriteBeans.filter { it.isFavorite }//过滤只有为true的值
            //找到当前点击进来的歌曲media
            val findCurrentMedia = allFilteredBeans.find { it.videoId == videoId }?.asMediaItem
            if (findCurrentMedia != null) {
                binding.likeAndDownloadLayout.visibility = View.VISIBLE
                updateInfoUi(findCurrentMedia)
                binding.playbackErrorLayout.visibility = View.GONE
                binding.totalDurationTv.visibility = View.GONE
                meController?.let {
                    it.setMediaItem(findCurrentMedia, true)
                    it.prepare()
                    it.play()
                    val mediaItems =
                        allFilteredBeans.map { mapAll -> mapAll.asMediaItem }//转换成MediaItem
                            .filter { filter -> filter.mediaId != videoId }//过滤掉id相等的。
                    it.addMediaItems(mediaItems)
                }
                updatePlayListDataAndAdapter()
            } else {
                binding.playbackErrorLayout.visibility = View.VISIBLE
            }
        } else {
            LogD(TAG, "从点击任意歌曲进入")
            binding.nameTv.text = intent.getStringExtra(PLAY_DETAILS_NAME)
            binding.descTv.text = intent.getStringExtra(PLAY_DETAILS_DESC)

            if (videoId.isNullOrEmpty()) {
                finish()
                return
            }
            //要加载数据的话就隐藏喜欢和下载按钮
            binding.likeAndDownloadLayout.visibility = View.GONE
            //传入进来的ID，就是进入此界面的当前ID
            currentVideoID = videoId
            //根据进来界面的当前ID来获取资源。
            initData(
                videoId, playlistId, playlistSetVideoId, params
            )
        }
        loadAd()
        initDownloadFlow()
        onReceive()
    }

    private suspend fun onReceive() {
        while (isActive) {
            select<Unit> {
                events.onReceive {
                    when (it) {
                        Event.ActivityOnResume -> {
                            activityOnResume()
                        }

                        else -> {}
                    }
                }
                requests.onReceive {
                    when (it) {
                        is Request.OnFavorites -> {
                            if (meController != null && meController.currentMediaItem != null) {
                                val currentMediaItem = meController.currentMediaItem
                                val jsonObject = JSONObject()
                                jsonObject.put(
                                    "song_title", "${currentMediaItem?.mediaMetadata?.title}"
                                )
                                val songMap = mutableMapOf(
                                    Pair(
                                        AnalysisUtil.PARAM_VALUE, jsonObject.toString()
                                    )
                                )
                                val currentFavoriteBean =
                                    App.appFavoriteDBManager.getFavoriteBeanByID(currentMediaItem?.mediaId!!)
                                if (currentFavoriteBean != null) {
                                    currentFavoriteBean.isFavorite = !currentFavoriteBean.isFavorite
                                    App.appFavoriteDBManager.updateFavoriteBean(currentFavoriteBean)
                                    if (currentFavoriteBean.isFavorite) {
                                        AnalysisUtil.logEvent(
                                            AnalysisUtil.PLAYER_B_LOVE_CLICK, songMap
                                        )
                                    } else {
                                        AnalysisUtil.logEvent(
                                            AnalysisUtil.PLAYER_B_UN_LOVE_CLICK, songMap
                                        )
                                    }
                                } else {
                                    insertFavoriteData(currentMediaItem)
                                    AnalysisUtil.logEvent(AnalysisUtil.PLAYER_B_LOVE_CLICK, songMap)
                                }
                                requests.trySend(Request.UpdateFavorite(currentMediaItem.mediaId))
                            }
                        }

                        is Request.OnDownload -> {
                            LolAdWrapper.shared.showAdTiming(
                                this@MoPlayDetailsActivity, AdPlacement.INST_DOWNLOAD
                            )

                            insertOfflineData(it.mediaItem)
                            val jsonObject = JSONObject()
                            jsonObject.put(
                                "download_id", "${it.mediaItem.mediaId}"
                            )
                            val songMap = mutableMapOf(
                                Pair(
                                    AnalysisUtil.PARAM_VALUE, jsonObject.toString()
                                )
                            )
                            AnalysisUtil.logEvent(AnalysisUtil.PLAYER_B_DOWNLOAD_CLICK, songMap)

                            LolAdWrapper.shared.loadAdIfNotCached(
                                this@MoPlayDetailsActivity, AdPlacement.INST_DOWNLOAD
                            )
                        }

                        is Request.UpdateFavorite -> {
                            val currentFavoriteBean =
                                App.appFavoriteDBManager.getFavoriteBeanByID(it.id)
                            LogD(TAG, "UpdateFavorite->${currentFavoriteBean}")
                            if (currentFavoriteBean != null) {
                                updateFavoriteUi(currentFavoriteBean.isFavorite)
                            } else {
                                updateFavoriteUi(false)
                            }
                        }
                    }
                }
            }
        }
    }

    private suspend fun activityOnResume() {
        //更新收藏按钮状态
//        if (meController != null && meController.currentMediaItem != null) {
//            val currentMediaItem = meController.currentMediaItem
//            val currentFavoriteBean =
//                App.appFavoriteDBManager.getFavoriteBeanByID(currentMediaItem?.mediaId!!)
//            if (currentFavoriteBean != null) {
//                updateFavoriteUi(currentFavoriteBean.isFavorite)
//            }
//        }
    }

    private fun initDownloadFlow() {
        ViewModelMain.modelDownloadsFlow.observe(this) { downloads ->
            if (meController != null && meController.currentMediaItem != null) {
                val id = meController.currentMediaItem?.mediaId
                LogD(TAG, "initDownloadFlow id ->${id}")
                val currentScreenDownloads = downloads[id]
                if (currentScreenDownloads != null) {
                    LogD(TAG, "updateDownloadUI id->${currentScreenDownloads.request.id}")
                    updateDownloadUI(currentScreenDownloads)
                }
            }
        }
    }

    private fun updateDownloadUI(download: Download) {
        when (download.state) {
            Download.STATE_DOWNLOADING -> {
                binding.downloadLoading.visibility = View.VISIBLE
                binding.downloadImg.setImageResource(R.drawable.download_icon)
                binding.downloadImg.visibility = View.GONE

                binding.downloadBtn.isClickable = false
                binding.downloadBtn.isEnabled = false
            }

            Download.STATE_COMPLETED -> {
                binding.downloadLoading.visibility = View.GONE
                binding.downloadImg.setImageResource(R.drawable.download_done_icon)
                binding.downloadImg.visibility = View.VISIBLE

                val jsonObject = JSONObject()
                jsonObject.put(
                    "download_id", download.request.id
                )
                val songMap = mutableMapOf(
                    Pair(
                        AnalysisUtil.PARAM_VALUE, jsonObject.toString()
                    )
                )
                AnalysisUtil.logEvent(AnalysisUtil.PLAYER_B_DOWNLOAD_SUCCESS_ACTION, songMap)
            }

            Download.STATE_FAILED -> {
                binding.downloadLoading.visibility = View.GONE
                binding.downloadImg.setImageResource(R.drawable.error)
                binding.downloadImg.visibility = View.VISIBLE

                binding.downloadBtn.isClickable = true
                binding.downloadBtn.isEnabled = true
            }

            else -> {
                binding.downloadLoading.visibility = View.GONE
                binding.downloadImg.setImageResource(R.drawable.download_icon)
                binding.downloadImg.visibility = View.VISIBLE

                binding.downloadBtn.isClickable = true
                binding.downloadBtn.isEnabled = true
            }
        }
    }

    private fun updateDownloadUi(id: String) {
        if (DownloadUtil.downloadResourceExist(id)) {//已经下载，按钮不可点击
            binding.downloadImg.setImageResource(R.drawable.download_done_icon)
            binding.downloadBtn.isClickable = false
            binding.downloadBtn.isEnabled = false
        } else {
            binding.downloadLoading.visibility = View.GONE
            binding.downloadImg.setImageResource(R.drawable.download_icon)
            binding.downloadImg.visibility = View.VISIBLE
            binding.downloadBtn.isClickable = true
            binding.downloadBtn.isEnabled = true
        }
    }

    private fun updateFavoriteUi(b: Boolean) {
        if (b) {
            binding.favoritesImg.setImageResource(R.drawable.favorited_icon)
        } else {
            binding.favoritesImg.setImageResource(R.drawable.not_favorited_icon)
        }
    }

    private fun initPlayerListener() {
        meController?.addListener(playerListener)
    }

    private fun updateCurrentMediaItemInfo() {
        if (meController != null && meController.currentMediaItem != null) {
            binding.playbackErrorLayout.visibility = View.GONE
            binding.loadingView.visibility = View.GONE
            binding.disableClicksLayout.visibility = View.GONE
            val currentString =
                convertMillisToMinutesAndSecondsString(MediaControllerManager.getCurrentPosition())
            binding.progressDurationTv.text = currentString
            if (MediaControllerManager.getDuration() > 0) {
                binding.totalDurationTv.visibility = View.VISIBLE
            } else {
                binding.totalDurationTv.visibility = View.GONE
            }

            binding.totalDurationTv.text =
                convertMillisToMinutesAndSecondsString(MediaControllerManager.getDuration())
            binding.sbProgress.valueTo = MediaControllerManager.getDuration().toFloat()
            val value = MediaControllerManager.getCurrentPosition().toFloat()
            if (binding.sbProgress.valueTo > value) {
                binding.sbProgress.value = MediaControllerManager.getCurrentPosition().toFloat()
            }
            updateProgressState()

            binding.progressBar.progress = MediaControllerManager.getBufferedPosition().toInt()
            binding.progressBar.max = MediaControllerManager.getDuration().toInt()
            updateProgressBufferingState()
            updatePlayListDataAndAdapter()
        }
    }

    @SuppressLint("NotifyDataSetChanged")
    private fun updatePlayListDataAndAdapter() {
        if (meController != null && meController.currentMediaItem != null) {
            val mediaItemCount = meController.mediaItemCount
            val allMediaItems: MutableList<MediaItem> = mutableListOf()
            for (index in 0 until mediaItemCount) {
                val mediaItemAt = meController.getMediaItemAt(index)
                allMediaItems.add(mediaItemAt)
            }
            playList.clear()
            playList.addAll(allMediaItems)
            detailsPlayListAdapter?.notifyDataSetChanged()
        }
    }

    private var playList: MutableList<MediaItem> = mutableListOf()

    private fun initPlayListAdapter() {
        detailsPlayListAdapter = DetailsPlayListAdapter(
            this@MoPlayDetailsActivity, playList
        )
        binding.playListRv.layoutManager = LinearLayoutManager(
            this@MoPlayDetailsActivity, LinearLayoutManager.VERTICAL, false
        )
        binding.playListRv.adapter = detailsPlayListAdapter
    }

    @SuppressLint("NotifyDataSetChanged")
    private fun initClick() {
        binding.backBtn.setOnClickListener {
            finish()
        }
        binding.tryAgainBtn.setOnClickListener {
            if (meController != null) {
                updateInfoUi(meController.currentMediaItem)
                updateProgressState()
                if (!meController.isPlaying) {
                    meController.prepare()
                    meController.play()
                }
            }
        }
        binding.playModeBtn.setOnClickListener {
            if (meController != null) {
                val playModeCounter = (appStore.playMusicMode + 1) % 3
                appStore.playMusicMode = when (playModeCounter) {
                    0 -> PlayMode.LIST_LOOP.value
                    1 -> PlayMode.SINGLE_LOOP.value
                    else -> PlayMode.RANDOM.value
                }
                when (AppStore(this).playMusicMode) {
                    PlayMode.LIST_LOOP.value -> {
                        meController.repeatMode = Player.REPEAT_MODE_ALL
                        meController.shuffleModeEnabled = false
                    }

                    PlayMode.SINGLE_LOOP.value -> {
                        meController.repeatMode = Player.REPEAT_MODE_ONE
                        meController.shuffleModeEnabled = false
                    }

                    PlayMode.RANDOM.value -> {
                        meController.repeatMode = Player.REPEAT_MODE_ALL
                        meController.shuffleModeEnabled = true
                    }
                }
                updatePlayModeUi()
                LogD(TAG, "repeatMode->${meController.repeatMode}")
                LogD(TAG, "shuffleModeEnabled->${meController.shuffleModeEnabled}")
            }
        }
        binding.playLayoutBtn.setOnClickListener {
            if (meController != null) {
                if (meController.isPlaying) {
                    meController.pause()
                    updatePlayState(false)
                } else {
                    meController.play()
                    updatePlayState(true)
                }
                updateProgressState()
            }
        }
        binding.playSkipBackBtn.setOnClickListener {
            LolAdWrapper.shared.showAdTiming(this, AdPlacement.INST_CUTTING_SONG)
            if (meController != null) {
                meController.seekToPreviousMediaItem()
                updateProgressUi()
                updateInfoUi(meController.currentMediaItem)
                updateProgressState()
                if (!meController.isPlaying) {
                    meController.prepare()
                    meController.play()
                }
            }
            LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_CUTTING_SONG)
        }
        binding.playSkipForwardBtn.setOnClickListener {
            LolAdWrapper.shared.showAdTiming(this, AdPlacement.INST_CUTTING_SONG)
            if (meController != null) {
                meController.seekToNextMediaItem()
                updateProgressUi()
                updateInfoUi(meController.currentMediaItem)
                updateProgressState()
                if (!meController.isPlaying) {
                    meController.prepare()
                    meController.play()
                }
            }
            LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_CUTTING_SONG)
        }
        binding.listLayoutBtn.setOnClickListener {
            toggleBottomLayout()
        }
        binding.bottomCloseBtn.setOnClickListener {
            toggleBottomLayout()
        }
        binding.bottomBlankLayout.setOnClickListener {
            toggleBottomLayout()
        }
        binding.progressBar.progress = 0
        binding.sbProgress.value = 0f
        binding.sbProgress.addOnChangeListener { slider, value, fromUser ->
            if (fromUser) {
                if (meController != null) {
                    meController.seekTo(value.toLong())
                    val ss = meController.isPlaying
                    if (!ss) {
                        meController.play()
                    }
                }
            }
        }
        binding.favoritesBtn.setOnClickListener {
            requests.trySend(Request.OnFavorites)
        }
        binding.downloadBtn.setOnClickListener {
            if (meController != null && meController.currentMediaItem != null) {
                val currentMediaItem = meController.currentMediaItem
                val contentId = currentMediaItem?.mediaId ?: ""
                //如果已经存在就不进行下载
                if (DownloadUtil.downloadResourceExist(contentId)) {
                    return@setOnClickListener
                }

                val downloadRequest = DownloadRequest.Builder(contentId, contentId.toUri())
                    .setCustomCacheKey(contentId).build()

                val downloadCount = DownloadUtil.getCurrentDownloads()
                if (downloadCount >= 3) {
                    Toast.makeText(this, getString(R.string.download_tips), Toast.LENGTH_LONG)
                        .show()
                } else {
                    DownloadService.sendAddDownload(
                        this, MyDownloadService::class.java, downloadRequest, false
                    )

                    requests.trySend(Request.OnDownload(currentMediaItem!!))
                }
            }
        }
    }

    private fun updatePlayModeUi() {
        binding.modePlayImg.setImageResource(
            when (AppStore(this).playMusicMode) {
                PlayMode.LIST_LOOP.value -> {
                    R.drawable.mode_cycle_play_icon
                }

                PlayMode.SINGLE_LOOP.value -> {
                    R.drawable.mode_single_play_icon
                }

                PlayMode.RANDOM.value -> {
                    R.drawable.mode_random_play_icon
                }

                else -> {
                    R.drawable.mode_cycle_play_icon
                }
            }

        )
    }

    @SuppressLint("NotifyDataSetChanged")
    private fun initData(
        videoId: String,
        playlistId: String? = null,
        playlistSetVideoId: String? = null,
        parameters: String? = null
    ) {
        SongRadio(
            videoId, playlistId, playlistSetVideoId, parameters
        ).let {
            launch(Dispatchers.Main) {
                val songRadioList = it.process()//获取到的资源集合

                if (songRadioList.isEmpty()) {//集合为空则展示错误提示
                    binding.loadingView.visibility = View.GONE
                    binding.disableClicksLayout.visibility = View.GONE
                    binding.playbackErrorLayout.visibility = View.VISIBLE
                }

                if (isFinishing) {
                    return@launch
                }

                var mediaItem: MediaItem? = null
                for (song: Innertube.SongItem in songRadioList) {
                    if (song.key == currentVideoID) {//判断当前ID得到一个mediaItem
                        mediaItem = song.asMediaItem
                        break
                    }
                }

                if (mediaItem != null) {
                    //数据请求完毕mediaItem不等于空就显示喜欢与下载按钮
                    binding.likeAndDownloadLayout.visibility = View.VISIBLE
                    updateInfoUi(mediaItem)

                    binding.playbackErrorLayout.visibility = View.GONE

                    binding.totalDurationTv.visibility = View.GONE


                    val newMediaItem = MediaItem.Builder().setMediaId(videoId).setUri(videoId)
                        .setCustomCacheKey(videoId).setMediaMetadata(
                            mediaItem.mediaMetadata
                        ).build()

                    meController?.let {
                        it.setMediaItem(newMediaItem, true)
                        it.prepare()
                        it.play()

                        //过滤掉进入页面的id得到集合addMediaItems
                        val mediaItems = songRadioList.map(Innertube.SongItem::asMediaItem)
                            .filter { filter -> filter.mediaId != videoId }
                        it.addMediaItems(mediaItems)
                    }

                    updatePlayListDataAndAdapter()
                } else {
                    binding.playbackErrorLayout.visibility = View.VISIBLE
                }
            }
        }
    }

    private val playerListener = object : Player.Listener {
        @SuppressLint("NotifyDataSetChanged")
        override fun onPositionDiscontinuity(
            oldPosition: Player.PositionInfo, newPosition: Player.PositionInfo, reason: Int
        ) {
            //保证自动播放完毕当前歌曲与通知切换歌曲可以更新UI信息
            if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION || reason == Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT) {
                updateProgressUi()
                updateInfoUi(meController?.currentMediaItem)
                if (detailsPlayListAdapter != null) {
                    detailsPlayListAdapter?.notifyDataSetChanged()
                }
            }
        }

        override fun onPlayerError(error: PlaybackException) {
            LogD(TAG, "onPlayerError error= $error")
            binding.playbackErrorLayout.visibility = View.VISIBLE//展示错误提示

            updatePlayState(false)
        }

        override fun onPlayWhenReadyChanged(
            playWhenReady: Boolean, reason: Int
        ) {
            updatePlayState(playWhenReady)
            updateProgressState()
        }

        override fun onPlaybackStateChanged(playbackState: Int) {
            when (playbackState) {
                Player.STATE_BUFFERING -> {
                    startPlayTime = System.currentTimeMillis()
                    LogD(TAG, "details STATE_BUFFERING")
                    binding.loadingView.visibility = View.VISIBLE
                    binding.disableClicksLayout.visibility = View.VISIBLE
                    binding.playbackErrorLayout.visibility = View.GONE
                }

                Player.STATE_READY -> {
                    val jsonObject = JSONObject()
                    jsonObject.put("play_time", System.currentTimeMillis() - startPlayTime)
                    val map = mutableMapOf(Pair(AnalysisUtil.PARAM_VALUE, jsonObject.toString()))
                    AnalysisUtil.logEvent(AnalysisUtil.PLAYER_B_DELAY_ACTION, map)
                    startPlayTime = 0L
                    LogD(TAG, "details STATE_READY")
                    AnalysisUtil.logEvent(AnalysisUtil.PLAYER_B_SUCCESS_ACTION)
                    binding.playbackErrorLayout.visibility = View.GONE
                    binding.loadingView.visibility = View.GONE
                    binding.disableClicksLayout.visibility = View.GONE
                    binding.totalDurationTv.visibility = View.VISIBLE
                    binding.totalDurationTv.text = convertMillisToMinutesAndSecondsString(
                        MediaControllerManager.getDuration()
                    )
                    binding.sbProgress.valueTo = MediaControllerManager.getDuration().toFloat()
                    binding.progressBar.max = MediaControllerManager.getDuration().toInt()
                    updateProgressBufferingState()
                }

                else -> {
                    binding.loadingView.visibility = View.GONE
                    binding.disableClicksLayout.visibility = View.GONE
                }
            }
            updateProgressState()
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        meController?.removeListener(playerListener)
    }

    private fun updateProgressUi() {
        binding.sbProgress.value = 0f
        binding.progressBar.progress = 0
        binding.progressDurationTv.text = convertMillisToMinutesAndSecondsString(0L)
        binding.totalDurationTv.visibility = View.GONE
    }

    private fun updateInfoUi(mediaItem: MediaItem?) {
        if (mediaItem == null) {
            binding.playbackErrorLayout.visibility = View.VISIBLE
            return
        }
//        currentVideoID = mediaItem.mediaId
        updateDownloadUi(mediaItem.mediaId)
        requests.trySend(Request.UpdateFavorite(mediaItem.mediaId))//更新喜欢状态

        val currentDownload = DownloadUtil.getCurrentIdDownload(mediaItem.mediaId)
        if (currentDownload != null) {
            updateDownloadUI(currentDownload)
        }


        Glide.with(this).asBitmap().load(mediaItem.mediaMetadata.artworkUri)
            .placeholder(R.mipmap.app_logo).into(object : CustomTarget<Bitmap>() {
                override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
                    binding.thumbnail.setImageBitmap(resource)
                    val blurredBitmap = applyGaussianBlur(resource, 25f, this@MoPlayDetailsActivity)
                    binding.imageView.setImageBitmap(blurredBitmap)
                }

                override fun onLoadCleared(placeholder: Drawable?) {
                    if (placeholder != null) {
                        binding.thumbnail.setImageDrawable(placeholder)
                    }
                }
            })

        binding.nameTv.text = mediaItem.mediaMetadata.title
        binding.descTv.text = mediaItem.mediaMetadata.artist
    }

    /**
     * 更新播放进度
     */
    private fun updateProgressState() {
        //判断是否ready与播放中，否则停止更新进度
        if (meController != null && meController.playbackState == Player.STATE_READY && meController.isPlaying) {
            updatePlayState(meController.isPlaying)
            progressHandler.removeCallbacksAndMessages(null)
            progressHandler.sendEmptyMessage(1)
        } else {
            progressHandler.removeCallbacksAndMessages(null)
        }
    }

    /**
     * 播放进度
     */
    private val progressHandler = object : Handler(Looper.myLooper()!!) {
        override fun handleMessage(msg: Message) {
            //判断是否ready与播放中，否则停止更新进度
            if (meController != null && meController.playbackState == Player.STATE_READY && meController.isPlaying) {
                val currentPosition = MediaControllerManager.getCurrentPosition()
                val currentString = convertMillisToMinutesAndSecondsString(currentPosition)
                binding.progressDurationTv.text = currentString

                val currentBufferedPosition = MediaControllerManager.getBufferedPosition()
                binding.progressBar.progress = currentBufferedPosition.toInt()


                val value = currentPosition.toFloat()
                if (binding.sbProgress.valueTo > value) {
                    binding.sbProgress.value = currentPosition.toFloat()
                }

                sendEmptyMessageDelayed(1, 50)
            }
        }
    }

    /**
     * 更新缓冲进度
     */
    private fun updateProgressBufferingState() {
        if (meController != null && meController.isLoading) {
            progressBufferingHandler.removeCallbacksAndMessages(null)
            progressBufferingHandler.sendEmptyMessage(1)
        } else {
            progressBufferingHandler.removeCallbacksAndMessages(null)
        }
    }

    /**
     * 缓冲进度
     */
    private val progressBufferingHandler = object : Handler(Looper.myLooper()!!) {
        override fun handleMessage(msg: Message) {
            if (meController != null && meController.isLoading) {
                val currentBufferedPosition = MediaControllerManager.getBufferedPosition()
                binding.progressBar.progress = currentBufferedPosition.toInt()
                sendEmptyMessageDelayed(1, 50)
            }
        }
    }

    private fun updatePlayState(b: Boolean) {
        if (b) {
            binding.playImg.setImageResource(R.drawable.playing_green_icon)
        } else {
            binding.playImg.setImageResource(R.drawable.play_green_icon)
        }
    }


    private fun toggleBottomLayout() {
        if (binding.bottomLayout.visibility == View.VISIBLE) {
            hideBottomLayout()
        } else {
            showBottomLayout()
        }
    }

    private fun showBottomLayout() {
        val slideUpAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_up)
        binding.bottomLayout.startAnimation(slideUpAnimation)
        binding.bottomLayout.visibility = View.VISIBLE
    }

    private fun hideBottomLayout() {
        val slideDownAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_down)
        binding.bottomLayout.startAnimation(slideDownAnimation)
        binding.bottomLayout.visibility = View.GONE
    }

    private fun loadAd() {
        LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_INTO_PLAY)
    }

    private fun showAD() {
        LolAdWrapper.shared.showAdTiming(this, AdPlacement.INST_INTO_PLAY)
    }
}