package com.adealink.weparty.profile.ui.about.adapter

import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.lifecycle.Lifecycle
import androidx.media3.common.C
import androidx.media3.common.Player.REPEAT_MODE_ONE
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.adealink.frame.aab.util.getCompatString
import com.adealink.frame.base.fastLazy
import com.adealink.frame.log.Log
import com.adealink.frame.router.Router
import com.adealink.frame.util.onClick
import com.adealink.weparty.commonui.ext.clearItemDecoration
import com.adealink.weparty.commonui.ext.dp
import com.adealink.weparty.commonui.ext.getActivity
import com.adealink.weparty.commonui.ext.gone
import com.adealink.weparty.commonui.ext.isViewValid
import com.adealink.weparty.commonui.ext.show
import com.adealink.weparty.commonui.recycleview.adapter.BindingViewHolder
import com.adealink.weparty.commonui.recycleview.adapter.MultiTypeListAdapter
import com.adealink.weparty.commonui.recycleview.adapter.multitype.ItemViewBinder
import com.adealink.weparty.commonui.recycleview.itemdecoration.GridSpacingItemDecoration
import com.adealink.weparty.exoplayer.ExoPlayerHelper
import com.adealink.weparty.module.profile.Profile
import com.adealink.weparty.profile.R
import com.adealink.weparty.profile.databinding.LayoutProfileDynamicBinding
import com.adealink.weparty.profile.dynamic.data.DynamicMediaData
import com.adealink.weparty.profile.dynamic.data.TAG_DYNAMIC
import com.adealink.weparty.profile.dynamic.util.updatePhotoMediaViewLp
import com.adealink.weparty.profile.ui.about.data.BaseDynamicPhotoItem
import com.adealink.weparty.profile.ui.about.data.DynamicEmptyItemData
import com.adealink.weparty.profile.ui.about.data.DynamicItemData
import com.adealink.weparty.profile.ui.about.data.DynamicPhotoItemData
import com.adealink.weparty.util.formatNumberStr
import com.adealink.weparty.util.formatTimeStr
import com.adealink.weparty.util.goImagePreviewActivity


class DynamicViewBinder(
    private val lifecycle: Lifecycle,
    private val onTalkClick: (item: DynamicItemData, position: Int) -> Unit,
    private val onLikeClick: (item: DynamicItemData, position: Int) -> Unit,
) : ItemViewBinder<DynamicItemData, DynamicViewBinder.ViewHolder>() {

    companion object {
        @JvmStatic
        private var isMute = true
    }

    // 用于在滚动时快速访问所有ViewHolder的Map
    private val viewHolderMap = mutableMapOf<Int, ViewHolder>()

    override fun onCreateViewHolder(
        inflater: LayoutInflater,
        parent: ViewGroup
    ): ViewHolder {
        return ViewHolder(LayoutProfileDynamicBinding.inflate(inflater, parent, false)).also {
            it.initView()
        }
    }

    @SuppressLint("SetTextI18n")
    override fun onBindViewHolder(
        holder: ViewHolder,
        item: DynamicItemData
    ) {
        viewHolderMap[holder.layoutPosition] = holder
        holder.binding.root.setPadding(
            0,
            16.dp(),
            0,
            if (holder.layoutPosition == adapter.itemCount - 1) 40.dp() else 0
        )
        holder.update(item)
    }

    fun playVideo(position: Int) {
        Log.d(TAG_DYNAMIC, "playVideo, position:$position")
        val pauseItems = mutableListOf<ViewHolder>()
        var resumeItem: ViewHolder? = null
        for (entry in viewHolderMap) {
            if (entry.key == position) {
                resumeItem = entry.value
            } else {
                pauseItems.add(entry.value)
            }
        }
        for (holder in pauseItems) {
            holder.resetPlay()
        }
        resumeItem?.resumePlay()
    }

    override fun onViewDetachedFromWindow(holder: ViewHolder) {
        super.onViewDetachedFromWindow(holder)
        holder.resetPlay()
    }

    override fun onViewRecycled(holder: ViewHolder) {
        super.onViewRecycled(holder)
        holder.resetPlay()
    }

    inner class ViewHolder(
        rootBinding: LayoutProfileDynamicBinding,
    ) : BindingViewHolder<LayoutProfileDynamicBinding>(rootBinding) {

        private var item: DynamicItemData? = null
        private val photoAdapter by fastLazy { MultiTypeListAdapter<BaseDynamicPhotoItem>() }

        private val gird2ItemDecoration = GridSpacingItemDecoration(2, 7.dp(), 0, false)
        private val gird3ItemDecoration = GridSpacingItemDecoration(3, 6.dp(), 6.dp(), false)

        //视频
        private var exoPlayerHelper: ExoPlayerHelper? = null

        fun initView() {
            binding.root.onClick {
                goDynamicDetail(false)
            }

            //图片
            photoAdapter.register(DynamicPhotoViewBinder { positon, item ->
                previewImage(positon)
            })
            photoAdapter.register(EmptyDynamicViewBinder { positon ->
                goDynamicDetail(false)
            })
            binding.rvPhoto.adapter = photoAdapter

            binding.vVideo.ivCover.setOptSize(false)

            binding.clTalk.onClick {
                item?.let { item ->
                    onTalkClick.invoke(item, layoutPosition)
                }
            }
            binding.clLike.onClick {
                item?.let { item ->
                    onLikeClick.invoke(item, layoutPosition)
                }
            }
            binding.clComment.onClick {
                goDynamicDetail(true)
            }
        }

        fun update(item: DynamicItemData) {
            this.item = item
            binding.ivAvatar.setImageUrl(item.userInfo?.avatar)
            binding.tvName.text = item.userInfo?.nickName
            //binding.tvName.text = "[${layoutPosition}] ${item.userInfo?.nickName}"
            binding.tvTime.text = item.dynamic.createdAt.formatTimeStr()

            binding.tvContent.show(!item.dynamic.textContent.isNullOrEmpty())
            binding.tvContent.text = item.dynamic.textContent

            if (item.dynamic.likeCount > 0) {
                binding.tvLike.text = formatNumberStr(item.dynamic.likeCount)
            } else {
                binding.tvLike.text = getCompatString(R.string.profile_dynamic_like)
            }

            if (item.dynamic.isVideo()) {
                binding.rvPhoto.gone()
                val videoMedia = item.dynamic.getVideoMedia()
                setVideo(videoMedia)
            } else {
                binding.vVideo.root.gone()
                resetVideo()
                setPhoto(item, item.dynamic.getPhotoMedia())
            }

            if (item.dynamic.liked) {
                binding.ivLike.setImageResource(R.drawable.profile_dynamic_liked_ic)
            } else {
                binding.ivLike.setImageResource(R.drawable.profile_dynamic_like_ic)
            }
            if (item.dynamic.likeCount > 0) {
                binding.tvLike.text = formatNumberStr(item.dynamic.likeCount)
            } else {
                binding.tvLike.text = getCompatString(R.string.profile_dynamic_like)
            }
            if (item.dynamic.commentCount > 0) {
                binding.tvComment.text = formatNumberStr(item.dynamic.commentCount)
            } else {
                binding.tvComment.text = getCompatString(R.string.profile_dynamic_comment)
            }

            binding.vBottomDivider.show(layoutPosition < adapter.itemCount - 1)
        }

        @SuppressLint("UnsafeOptInUsageError")
        private fun setVideo(media: DynamicMediaData?) {
            if (media == null || media.url.isEmpty()) {
                resetVideo()
                binding.vVideo.root.gone()
                return
            }
            resetVideo()
            binding.vVideo.root.show()
            //设置视频控件比例
            updatePhotoMediaViewLp(
                binding.vVideo.clPlayer,
                media.getVideoCoverData(),
                horizontalWidth = 0, verticalWidth = 167.dp()
            )
            setVideoPreview(media)
            binding.vVideo.btnPlay.onClick {
                playVideo()
            }
            binding.vVideo.btnSound.onClick {
                muteVideo()
            }
        }

        fun setVideoPreview(media: DynamicMediaData?) {
            Log.d(TAG_DYNAMIC, "($this)setVideoPreview, $media")
            if (media == null || (media.url.isNullOrEmpty() && media.videoCover.isNullOrEmpty())) {
                binding.vVideo.ivCover.gone()
                return
            }
            binding.vVideo.ivCover.show()
            if (media.videoCover.isNullOrEmpty()) {
                binding.vVideo.ivCover.setImageUrl(media.url)
            } else {
                binding.vVideo.ivCover.setImageUrl(media.videoCover)
            }
        }

        fun resumePlay() {
            val videoMedia = this.item?.dynamic?.getVideoMedia()
            setVideoPreview(videoMedia)
            if (videoMedia == null || videoMedia.url.isEmpty()) {
                Log.d(TAG_DYNAMIC, "($this)resumePlay return, for videoUrl is empty")
                resetVideo()
                return
            }
            if (exoPlayerHelper != null && binding.vVideo.vPlayer.player?.isPlaying == true) {
                Log.d(TAG_DYNAMIC, "($this)resumePlay, already playing")
                return
            }
            Log.d(TAG_DYNAMIC, "($this)resumePlay")
            resetVideo()
            binding.vVideo.vLoading.show()
            initExoPlayer(videoMedia.url)
        }

        @SuppressLint("UnsafeOptInUsageError")
        private fun initExoPlayer(videoUrl: String) {
            exoPlayerHelper = ExoPlayerHelper
                .Builder(binding.root.context) { player ->
                    binding.vVideo.vPlayer.player = player
                }
                .uri(videoUrl)
                .scaleMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING)
                .repeatMode(REPEAT_MODE_ONE)
                .playWhenReady(true)
                .volume(
                    if (isMute) {
                        0f
                    } else {
                        1f
                    }
                )
                .playListener(
                    doOnReadyCallback = {
                        Log.d(TAG_DYNAMIC, "($this)doOnReadyCallback")
                        if (!this.isViewValid()) {
                            return@playListener
                        }
                        binding.vVideo.vLoading.gone()
                        binding.vVideo.ivCover.gone()

                        binding.vVideo.btnPlay.show()
                        binding.vVideo.btnSound.show()
                        updateMuteVideo()

                        binding.vVideo.tvDuration.show()
                        binding.vVideo.tvDuration.setDuration(
                            binding.vVideo.vPlayer.player?.duration ?: 0L
                        )
                    },
                    onPlayingChangedCallback = {
                        Log.d(TAG_DYNAMIC, "($this)onPlayingChangedCallback, isPlaying:$it")
                        onPlayingChanged(it)
                    },
                    onErrorCallback = {
                        Log.e(
                            TAG_DYNAMIC,
                            "($this), loadVideo(${videoUrl}) fail, ${it.message}",
                            it
                        )
                    }
                )
                .onPauseWhenBuffering {
                    onIsPlayingChangedForBuffering(it)
                }
                .build()
            exoPlayerHelper?.observe(lifecycle)
            Log.d(TAG_DYNAMIC, "($this)initExoPlayer, player:$exoPlayerHelper")
        }

        //重置播放状态, 恢复到待播放
        fun resetPlay() {
            Log.d(TAG_DYNAMIC, "($this)resetPlay")
            resetVideo()
            setVideoPreview(this.item?.dynamic?.getVideoMedia())
        }

        private fun playVideo() {
            val player = binding.vVideo.vPlayer.player
            if (player == null) {
                Log.d(TAG_DYNAMIC, "($this)playVideo return, for player is null")
                return
            }
            Log.d(TAG_DYNAMIC, "($this)playVideo")
            player.playWhenReady = true
        }

        private fun muteVideo() {
            val player = binding.vVideo.vPlayer.player
            if (player == null) {
                Log.d(TAG_DYNAMIC, "($this)muteVideo return, for player is null")
                return
            }
            if (player.volume > 0) {
                Log.d(TAG_DYNAMIC, "muteVideo, volume = 0f")
                player.volume = 0f
                isMute = true
            } else {
                Log.d(TAG_DYNAMIC, "muteVideo, volume = 1f")
                player.volume = 1f
                isMute = false
            }
            updateMuteVideo()
        }

        private fun updateMuteVideo() {
            if (!isViewValid()) {
                return
            }
            if (isMute) {
                binding.vVideo.btnSound.setImageResource(R.drawable.profile_dynamic_video_mute_ic)
            } else {
                binding.vVideo.btnSound.setImageResource(R.drawable.profile_dynamic_video_sound_ic)
            }
        }

        private fun onPlayingChanged(isPlaying: Boolean) {
            if (!isViewValid()) {
                return
            }
            Log.d(TAG_DYNAMIC, "($this)onPlayingChanged, isPlaying:$isPlaying")
            binding.vVideo.btnPlay.show(!isPlaying)
            if (isPlaying) {
                binding.vVideo.tvDuration.startTimer(
                    videoDuration = {
                        binding.vVideo.vPlayer.player?.duration ?: 0L
                    },
                    videoProgress = {
                        binding.vVideo.vPlayer.player?.currentPosition ?: 0L
                    },
                    isPlaying = {
                        binding.vVideo.vPlayer.player?.isPlaying ?: false
                    }
                )
            } else {
                binding.vVideo.tvDuration.reset()
            }
        }

        private fun onIsPlayingChangedForBuffering(isPlaying: Boolean) {
            if (!isViewValid()) {
                return
            }
            if (isPlaying) {
                binding.vVideo.vLoading.gone()
            } else {
                binding.vVideo.vLoading.show()
            }
        }

        private fun setPhoto(item: DynamicItemData, media: List<DynamicMediaData>?) {
            if (media.isNullOrEmpty()) {
                binding.vSinglePhoto.gone()
                binding.rvPhoto.gone()
                return
            }
            when (media.size) {
                1 -> {
                    //1张图片
                    binding.vSinglePhoto.show()
                    binding.rvPhoto.gone()
                    val photoMedia = media.getOrNull(0)
                    updatePhotoMediaViewLp(
                        binding.ivSingleImg,
                        photoMedia?.getPhotoData(),
                        horizontalWidth = 223.dp(), verticalWidth = 167.dp()
                    )
                    binding.ivSingleImg.setImageUrl(photoMedia?.url)
                    binding.ivSingleImg.onClick {
                        previewImage(0)
                    }
                }

                2 -> {
                    //2张图片
                    binding.vSinglePhoto.gone()
                    binding.rvPhoto.show()
                    binding.rvPhoto.layoutManager =
                        GridLayoutManager(binding.rvPhoto.context, 2, RecyclerView.VERTICAL, false)
                    binding.rvPhoto.clearItemDecoration()
                    binding.rvPhoto.addItemDecoration(gird2ItemDecoration)
                    val photoList = mutableListOf<BaseDynamicPhotoItem>()
                    photoList.add(DynamicPhotoItemData(media.getOrNull(0)))
                    photoList.add(DynamicPhotoItemData(media.getOrNull(1)))
                    photoList.add(DynamicEmptyItemData())
                    photoAdapter.submitList(photoList)
                }

                else -> {
                    //3张或以上图片
                    binding.vSinglePhoto.gone()
                    binding.rvPhoto.show()
                    binding.rvPhoto.layoutManager =
                        GridLayoutManager(binding.rvPhoto.context, 3, RecyclerView.VERTICAL, false)
                    binding.rvPhoto.clearItemDecoration()
                    binding.rvPhoto.addItemDecoration(gird3ItemDecoration)

                    val itemList = mutableListOf<BaseDynamicPhotoItem>()
                    itemList.addAll(
                        media.map {
                            DynamicPhotoItemData(it)
                        }
                    )
                    val lastLineCount = itemList.size % 3
                    if (lastLineCount != 0) {
                        for (i in 0 until 3 - lastLineCount) {
                            itemList.add(DynamicEmptyItemData())
                        }
                    }
                    photoAdapter.submitList(itemList)
                }
            }
        }

        private fun resetVideo() {
            binding.vVideo.btnSound.gone()
            binding.vVideo.btnPlay.gone()

            binding.vVideo.tvDuration.gone()
            binding.vVideo.tvDuration.reset()

            binding.vVideo.vPlayer.player = null
            exoPlayerHelper?.releasePlayer()
            exoPlayerHelper = null
        }

        private fun previewImage(position: Int) {
            val item = this.item ?: return
            val photoList = item.dynamic.getPhotoMedia()
            if (photoList == null || photoList.isEmpty()) {
                return
            }
            val photoArray = arrayListOf<String>()
            for (data in photoList) {
                photoArray.add(data.url)
            }
            val act = binding.root.getActivity() ?: return
            goImagePreviewActivity(
                act,
                photoArray,
                currentIndex = position
            )
        }

        private fun goDynamicDetail(showComment: Boolean) {
            val item = this.item
            if (item == null) {
                return
            }
            val act = binding.root.getActivity() ?: return
            Router.build(act, Profile.Dynamic.PATH)
                .putExtra(Profile.Dynamic.EXTRA_DYNAMIC_ID, item.dynamic.id)
                .putExtra(Profile.Dynamic.EXTRA_DYNAMIC_DATA, item.dynamic)
                .putExtra(Profile.Dynamic.EXTRA_DYNAMIC_USERINFO, item.userInfo)
                .putExtra(Profile.Dynamic.EXTRA_DYNAMIC_SHOW_COMMENT, showComment)
                .start()
        }

    }


}
