package com.gh.gamecenter.home.custom.adapter

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.databind.BindingAdapters
import com.gh.common.util.DownloadItemUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
import com.gh.gamecenter.common.utils.ImageUtils
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.common.utils.toBinding
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.view.AsyncCell
import com.gh.gamecenter.common.view.stacklayoutmanager2.StackLayoutManagerV2
import com.gh.gamecenter.core.utils.StringUtils
import com.gh.gamecenter.databinding.RecyclerFoldSlideLargeImageItemBinding
import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.exposure.IExposureProvider
import com.gh.gamecenter.feature.game.GameItemViewHolder
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.home.custom.eventlistener.SubjectEventHelper
import com.gh.gamecenter.home.custom.model.CustomSubjectItem
import com.lightgame.download.DownloadEntity
import splitties.views.backgroundColor

class CustomFoldSlideLargeImageItemAdapter(
    context: Context,
    private val eventHelper: SubjectEventHelper
) : CustomBaseChildAdapter<GameEntity, CustomFoldSlideLargeImageItemAdapter.ImageItemViewHolder>(context) {

    private lateinit var _data: CustomSubjectItem

    private var _recyclerView: RecyclerView? = null

    fun setData(data: CustomSubjectItem) {
        _data = data
        val games = data.data.data
        if (!games.isNullOrEmpty()) {
            val list = ArrayList<GameEntity>(games)
            while (list.size <= 5) {
                list.addAll(games)
            }
            submitList(list, true)
        }
    }

    override fun getKey(t: GameEntity): String {
        return t.id
    }

    override fun getItemCount(): Int {
        return if (dataList.isEmpty()) {
            0
        } else {
            Int.MAX_VALUE
        }
    }

    override fun getItem(position: Int): GameEntity {
        return dataList[position % (dataList.size)]
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageItemViewHolder {
        return ImageItemViewHolder(eventHelper, parent.toBinding())
    }

    override fun onViewDetachedFromWindow(holder: ImageItemViewHolder) {
        super.onViewDetachedFromWindow(holder)
        holder.dismissBubble()
    }

    override fun onBindViewHolder(holder: ImageItemViewHolder, position: Int) {
        val realPosition = position % dataList.size
        val game = getItem(realPosition)
        holder.bindView(realPosition, game, _data, this)
        holder.itemView.setOnClickListener {
            eventHelper.navigateToGameDetailPage(realPosition, game)
        }
    }

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        _recyclerView = recyclerView
    }

    override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
        _recyclerView = null
    }

    override fun notifyDownload(download: DownloadEntity) {
        forEach { position, game ->
            if (game.id == download.gameId) {
                notifyItemChanged(position, CustomPageAdapter.PAYLOAD_REFRESH_GAME_CHANGED)
                return@forEach
            }
        }
    }

    override fun notifyDownloadDeleted(status: EBDownloadStatus) {
        notifyChildItem(status.packageName)
    }

    override fun notifyInstalled(busFour: EBPackage) {
        notifyChildItem(busFour.packageName)
    }

    private fun notifyChildItem(packageName: String) {
        forEach { position, game ->
            val hasApk = game.getApk().any {
                it.packageName == packageName
            }
            if (hasApk) {
                notifyItemChanged(position, CustomPageAdapter.PAYLOAD_REFRESH_GAME_CHANGED)
            }
        }
    }

    private fun forEach(action: (Int, GameEntity) -> Unit) {
        (_recyclerView?.layoutManager as? StackLayoutManagerV2)?.let {
            val firstPosition = it.selectedPosition
            val visibleCount = it.visibleCount
            val endPosition = firstPosition + visibleCount - 1
            for (position in firstPosition..endPosition) {
                val game = getItem(position)
                action(position, game)
            }
        }
    }

    fun getInitPosition() =
        if (dataList.isEmpty()) {
            0
        } else {
            Int.MAX_VALUE / 2 - (Int.MAX_VALUE / 2) % dataList.size
        }

    class ImageItemViewHolder(
        private val eventHelper: SubjectEventHelper,
        val binding: RecyclerFoldSlideLargeImageItemBinding
    ) :
        RecyclerView.ViewHolder(binding.root), IExposureProvider {

        private lateinit var item: GameEntity

        fun bindView(
            childPosition: Int,
            game: GameEntity,
            data: CustomSubjectItem,
            adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder>
        ) {
            item = game

            if (game.isWechatMiniGame()) {
                ImageUtils.display(binding.poster, game.banner)
            } else {
                ImageUtils.display(binding.poster, game.homeSetting.image)
            }
            binding.ivIcon.displayGameIconWithIfShowSubscript(game, data.data.showIndexIconSubscript)
            binding.tvTitle.text = game.name
            GameItemViewHolder.initGameSubtitleAndAdLabelOnGameSubject(
                game,
                binding.tvSubTitle,
                binding.llTitle,
                binding.tvTitle,
                data.data.adIconActive,
                canShowTitle = data.data.showIndexSubtitle
            )

            MiniGameItemHelper.setMiniGameUsage(binding.gamePlayCount, game)

            binding.tvBubble.text = game.bubbleText
            binding.gStar.goneIf(!(data.data.showStar && game.commentCount > 3)) {
                binding.tvStar.text = if (game.star == 10.0F) "10" else game.star.toString()
            }
            BindingAdapters.setGameTags(binding.llLabel, game, "")
            binding.cvContainer.setCardBackgroundColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(itemView.context))

            try {
                getBottomBackground(game.homeSetting.placeholderColor)
            } catch (e: Exception) {
                null
            }?.let { (color, drawable) ->
                binding.vGradient.background = drawable
                binding.vBottomBackground.backgroundColor = color
            }

            if (data.shouldShowDownloadButton) {
                binding.btnDownload.goneIf(false)
                DownloadItemUtils.setOnClickListener(
                    itemView.context, binding.btnDownload, game, bindingAdapterPosition,
                    adapter,
                    StringUtils.buildString(
                        "(游戏-专题:",
                        "subjectData.name",
                        "-列表[",
                        (bindingAdapterPosition + 1).toString(),
                        "])"
                    ),
                    location = StringUtils.buildString("游戏-专题-", "subjectData.name", ":", game.name),
                    traceEvent = data.exposureEvent
                ) {
                    eventHelper.onDownloadButtonClick(childPosition, game)
                }
                DownloadItemUtils.updateItem(
                    itemView.context,
                    game,
                    CustomGameViewHolder(binding),
                    ""
                )
            } else {
                binding.btnDownload.goneIf(true)
            }
        }

        private fun getBottomBackground(oColor: String): Pair<Int, Drawable> {
            val colorInt = Color.parseColor(oColor)
            val red = Color.red(colorInt)
            val green = Color.green(colorInt)
            val blue = Color.blue(colorInt)
            val hsv = FloatArray(3)
            Color.RGBToHSV(red, green, blue, hsv)
            val s = 0.3f + 0.3f * hsv[1]
            val v = 0.3f + 0.3f * hsv[2]
            val targetHsv = FloatArray(3)
            targetHsv[0] = hsv[0]
            targetHsv[1] = s
            targetHsv[2] = v
            val startColor = Color.HSVToColor(0, targetHsv)
            val endColor = Color.HSVToColor(255, targetHsv)

            val drawable = GradientDrawable()
            drawable.colors = intArrayOf(startColor, endColor)
            drawable.orientation = GradientDrawable.Orientation.TOP_BOTTOM
            return endColor to drawable
        }

        private var valueAnimator: ValueAnimator? = null

        private val handler = object : Handler(Looper.getMainLooper()) {
            override fun handleMessage(msg: Message) {
                super.handleMessage(msg)
                startBubbleAnimation(false)
            }
        }

        fun showBubble() {
            if (item.bubbleText.isNotBlank() && !item.hasBubbleShowed) {
                item.hasBubbleShowed = true
                startBubbleAnimation(true)
            }
        }

        fun dismissBubble() {
            // 取消气泡的显示动画（如果有的话）
            valueAnimator?.cancel()
            valueAnimator = null
            // 取消气泡倒计时
            handler.removeCallbacksAndMessages(null)
            binding.tvBubble.alpha = 0f
        }

        private fun startBubbleAnimation(isShow: Boolean) {
            valueAnimator = ValueAnimator.ofFloat(0f, 1f).apply {
                duration = 300
                addUpdateListener {
                    val progress = it.animatedValue as Float
                    val scale = if (isShow) {
                        0.4 * progress + 0.6f
                    } else {
                        1 - progress * 0.4
                    }
                    val alpha = if (isShow) {
                        progress
                    } else {
                        1 - progress
                    }
                    binding.tvBubble.scaleX = scale.toFloat()
                    binding.tvBubble.scaleY = scale.toFloat()
                    binding.tvBubble.alpha = alpha

                    if (isShow && progress == 1.0f) {
                        handler.sendEmptyMessageDelayed(0, BUBBLE_SHOW_DURATION)
                    }
                }
                start()
            }
        }

        override fun provideExposureData(): ExposureEvent? {
            return item.exposureEvent?.getFreshExposureEvent()
        }

        companion object {
            private const val BUBBLE_SHOW_DURATION = 4000L
        }
    }

    class FoldSlideLargeImageItemCell(context: Context) : AsyncCell(context) {
        var binding: RecyclerFoldSlideLargeImageItemBinding? = null

        override val layoutId = R.layout.recycler_fold_slide_large_image_item
        override val delayFirstTimeBindView = false
        override fun createDataBindingView(view: View): View? {
            binding = RecyclerFoldSlideLargeImageItemBinding.bind(view)
            return view.rootView
        }
    }

    class CustomGameViewHolder(val binding: RecyclerFoldSlideLargeImageItemBinding) :
        GameViewHolder(binding.root) {

        init {
            gameDownloadBtn = binding.btnDownload
            multiVersionDownloadTv = binding.multiVersionDownloadTv
            gameDownloadTips = binding.downloadTipsLottie
        }

    }
}