package com.adealink.weparty.imageselect.view

import android.annotation.SuppressLint
import android.media.MediaMetadataRetriever
import android.media.MediaMetadataRetriever.OPTION_CLOSEST_SYNC
import android.os.Build
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.core.graphics.scale
import androidx.core.net.toUri
import com.adealink.frame.coroutine.dispatcher.Dispatcher
import com.adealink.frame.log.Log
import com.adealink.weparty.commonui.ext.gone
import com.adealink.weparty.commonui.ext.show
import com.adealink.weparty.commonui.recycleview.adapter.BindingViewHolder
import com.adealink.weparty.commonui.recycleview.adapter.multitype.ItemViewBinder
import com.adealink.weparty.databinding.ItemImageBinding
import com.adealink.weparty.imageselect.cache.videoCoverCache
import com.adealink.weparty.imageselect.listener.OnOperateListener
import com.adealink.weparty.imageselect.model.LocalMedia
import com.adealink.weparty.imageselect.util.PictureMimeType
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.android.asCoroutineDispatcher
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.Locale

class ImageItemViewBinder(
    private val l: OnOperateListener,
    private val multiChecked: Boolean = false
) :
    ItemViewBinder<LocalMedia, BindingViewHolder<ItemImageBinding>>(), CoroutineScope {

    private val serialHandler = Dispatcher.getSerialHandler()
    override val coroutineContext = SupervisorJob() + serialHandler.asCoroutineDispatcher()

    override fun onCreateViewHolder(
        inflater: LayoutInflater,
        parent: ViewGroup
    ): BindingViewHolder<ItemImageBinding> {
        val binding = ItemImageBinding.inflate(inflater, parent, false)
        binding.vCheckArea.visibility = if (multiChecked) View.VISIBLE else View.GONE
        binding.tvCount.visibility = if (multiChecked) View.VISIBLE else View.GONE
        binding.vMask.visibility = if (multiChecked) View.VISIBLE else View.GONE
        return BindingViewHolder(binding)
    }

    @SuppressLint("SetTextI18n")
    override fun onBindViewHolder(holder: BindingViewHolder<ItemImageBinding>, item: LocalMedia) {
        holder.binding.ivGifTag.visibility =
            if (PictureMimeType.isGif(item.mimeType)) View.VISIBLE else View.GONE

        holder.binding.root.setOnClickListener {
            if (PictureMimeType.eqVideo(item.mimeType)) {
                l.onSelectVideo(item)
            } else {
                l.onSelectImage(item)
            }
        }

        holder.binding.vCheckArea.setOnClickListener {
            l.onItemChecked(holder.bindingAdapterPosition)
        }

        if (item.isChecked) {
            holder.binding.tvCount.text = item.num.toString()
            holder.binding.tvCount.isSelected = true
        } else {
            holder.binding.tvCount.text = ""
            holder.binding.tvCount.isSelected = false
        }

        if (PictureMimeType.eqVideo(item.mimeType)) {
            holder.binding.videoDurationLayout.show()
            val seconds = item.duration / 1000
            val time = String.format(
                Locale.getDefault(), "%d:%02d",
                seconds / 60, seconds % 60
            )
            holder.binding.videoDurationTv.text = time
            showVideoCover(holder.binding.imageIv, item.uri)
        } else {
            holder.binding.videoDurationLayout.gone()
            holder.binding.imageIv.setImageUrl(item.uri)
        }
    }

    private fun showVideoCover(imageview: ImageView, uri: String?) {
        if(uri.isNullOrEmpty()) {
            return
        }
        val cache = videoCoverCache[uri]
        if (cache != null) {
            imageview.setImageBitmap(cache)
            return
        }
        imageview.setImageBitmap(null)
        imageview.tag = uri
        launch(Dispatcher.WENEXT_THREAD_POOL) {
            val retriever = MediaMetadataRetriever()
            try {
                retriever.setDataSource(imageview.context, uri.toUri())
                val frame = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
                    retriever.getScaledFrameAtTime(-1, OPTION_CLOSEST_SYNC, 256, 256)
                } else {
                    retriever.frameAtTime?.scale(256, 256)
                }
                frame?.let {
                    videoCoverCache.put(uri, it)
                }
                withContext(Dispatchers.Main) {
                    if (imageview.tag == uri) {
                        imageview.setImageBitmap(frame)
                    }
                }
            } catch (e: Exception) {
                Log.e("ImageItemViewBinder", "setDataSource failed for uri: $uri", e)
            } finally {
                retriever.release()
            }
        }
    }

}