package com.gh.gamecenter.home.slide

import android.graphics.Typeface
import android.graphics.drawable.GradientDrawable
import android.view.MotionEvent
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.graphics.ColorUtils
import androidx.core.view.isVisible
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.gh.common.exposure.ExposureManager
import com.gh.common.util.DirectUtils
import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.DrawableView
import com.gh.gamecenter.common.view.FixLinearLayoutManager
import com.gh.gamecenter.common.view.ScrollEventListener
import com.gh.gamecenter.common.view.TouchSlopRecyclerView
import com.gh.gamecenter.core.utils.AlphaGradientProcess
import com.gh.gamecenter.core.utils.MtaHelper
import com.gh.gamecenter.databinding.HomeSlideCardItemBinding
import com.gh.gamecenter.databinding.HomeSlideWithCardsBinding
import com.gh.gamecenter.entity.HomeSubSlide
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.exposure.ExposureSource
import com.gh.gamecenter.feature.exposure.ExposureType
import com.gh.gamecenter.home.HomeItemData
import com.gh.gamecenter.home.HomeViewModel
import splitties.views.dsl.core.endMargin
import kotlin.math.abs

class HomeSlideWithCardsViewHolder(
    val binding: HomeSlideWithCardsBinding,
    val viewModel: HomeViewModel,
    val callback: (colorStr: Int) -> Unit
) : BaseRecyclerViewHolder<Any>(binding.root) {
    private var mSnapHelper: PagerSnapHelper? = null
    private var mLastX: Int = 0
    private var mLastY: Int = 0

    fun bindSlideWithCards(
        itemData: HomeItemData,
        basicExposureSource: List<ExposureSource>
    ) {
        bindSlide(itemData, basicExposureSource)
        bindCards(itemData, basicExposureSource)
    }

    private fun bindSlide(itemData: HomeItemData, basicExposureSource: List<ExposureSource>) {
        val slideList = itemData.slides!!
        val context = binding.recyclerView.context
        var adapter = binding.recyclerView.adapter

        itemData.exposureEventList = itemData.exposureEventList ?: arrayListOf()

        if (adapter is HomeSlideListAdapter) {
            adapter.itemData = itemData
            adapter.checkResetData(slideList)

            val layoutManager = binding.recyclerView.layoutManager
            if (layoutManager != null) {
                val view = mSnapHelper?.findSnapView(layoutManager)
                var curPosition = 0
                if (view != null) {
                    curPosition = adapter.getActualPosition(layoutManager.getPosition(view))
                }
                updateImmersiveColor(
                    slideList.safelyGetInRelease(curPosition)?.placeholderColor?.hexStringToIntColor()
                        ?: R.color.background_white.toColor(binding.root.context)
                )
            }

            return
        }

        mSnapHelper = PagerSnapHelper()
        val layoutManager = FixLinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
        adapter = HomeSlideListAdapter(
            context,
            itemData,
            layoutManager,
            mSnapHelper!!,
            binding.recyclerView,
            basicExposureSource,
            true
        )
        (binding.recyclerView.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
        binding.recyclerView.layoutManager = layoutManager
        binding.recyclerView.adapter = adapter
        binding.recyclerView.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
            override fun onViewAttachedToWindow(v: View) {
                // do nothing
            }

            override fun onViewDetachedFromWindow(v: View) {
                adapter.stopScroll()
            }
        })
        binding.recyclerView.scrollToPosition(adapter.getActualFirstPositionInCenter())
        mSnapHelper?.attachToRecyclerView(binding.recyclerView)
        binding.bannerIndicator.run {
            mPageSize = adapter.getActualSize()
            notifyDataChanged()
        }
        binding.recyclerView.addOnItemTouchListener(object : RecyclerView.SimpleOnItemTouchListener() {
            override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
                val x = e.x.toInt()
                val y = e.y.toInt()

                when (e.action) {
                    MotionEvent.ACTION_DOWN -> {
                        mLastX = e.x.toInt()
                        mLastY = e.y.toInt()
                        rv.parent.parent.requestDisallowInterceptTouchEvent(true)
                    }
                    MotionEvent.ACTION_UP -> rv.parent.parent.requestDisallowInterceptTouchEvent(
                        false
                    )
                    MotionEvent.ACTION_MOVE -> {
                        val deltaX: Int = x - mLastX
                        val deltaY: Int = y - mLastY
                        val isHorizontalScroll = abs(deltaX) > abs(deltaY)
                        rv.parent.parent.requestDisallowInterceptTouchEvent(isHorizontalScroll)
                    }
                }

                val isStop =
                    e.action == MotionEvent.ACTION_DOWN || e.action == MotionEvent.ACTION_MOVE
                if (isStop) adapter.stopScroll() else adapter.startScroll()

                val touchSlopRecyclerView = binding.recyclerView.parent.parent.parent
                if (touchSlopRecyclerView is TouchSlopRecyclerView) {
                    touchSlopRecyclerView.touchSlopEnabled = isStop
                } else throwExceptionInDebug("TouchSlopRecyclerView not found")
                return false
            }
        })
        binding.recyclerView.addOnScrollListener(ScrollEventListener(binding.recyclerView).apply {
            setOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
                var lastStatePosition = -1
                var lastScrollState = RecyclerView.SCROLL_STATE_IDLE

                override fun onPageScrollStateChanged(state: Int) {
                    super.onPageScrollStateChanged(state)

                    if (scrollState == RecyclerView.SCROLL_STATE_IDLE) {
                        val view = mSnapHelper?.findSnapView(layoutManager)
                        var curPosition = 0
                        if (view != null) {
                            curPosition = adapter.getActualPosition(layoutManager.getPosition(view))
                        }
                        if (lastScrollState == RecyclerView.SCROLL_STATE_DRAGGING && curPosition != lastStatePosition) {
                            MtaHelper.onEvent(
                                "首页_新",
                                "轮播_滑动",
                                if (curPosition > lastStatePosition) "左滑" else "右滑"
                            )
                        }
                        lastStatePosition = curPosition
                        lastScrollState = scrollState
                        updateImmersiveColor(
                            slideList.safelyGetInRelease(curPosition)?.placeholderColor?.hexStringToIntColor()
                                ?: R.color.background_white.toColor(binding.root.context)
                        )
                    } else if (scrollState == RecyclerView.SCROLL_STATE_DRAGGING) {
                        lastScrollState = scrollState
                    }
                }

                override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
                    super.onPageScrolled(position, positionOffset, positionOffsetPixels)
                    binding.bannerIndicator.onPageScrolled(
                        adapter.getActualPosition(position),
                        positionOffset
                    )

                    val currentPosition = adapter.getActualPosition(position)
                    val nextPosition = adapter.getActualPosition(position + 1)

                    val currentColor =
                        slideList.safelyGetInRelease(currentPosition)?.placeholderColor?.hexStringToIntColor()
                            ?: R.color.background_white.toColor(binding.root.context)
                    val nextColor = slideList.safelyGetInRelease(nextPosition)?.placeholderColor?.hexStringToIntColor()
                        ?: currentColor

                    val colorInBetween =
                        ColorUtils.blendARGB(currentColor, nextColor, positionOffset)

                    updateImmersiveColor(colorInBetween)
                }
            })
        })
        updateImmersiveColor(slideList[0].placeholderColor.hexStringToIntColor())
    }

    private fun bindCards(itemData: HomeItemData, basicExposureSource: List<ExposureSource>) {
        itemData.homeSubSlides?.let {
            bindCard(itemData, binding.firstCv, it[0], basicExposureSource, 0)
            bindCard(itemData, binding.secondCv, it[1], basicExposureSource, 1)
        }
    }

    private fun getCardTypeChinese(type: String) = when (type) {
        "column" -> "游戏专题"
        "column_collection" -> "专题合集"
        "column_test_v2" -> "新游开测"
        "server" -> "开服表"
        "game_explore" -> "发现页"
        "game_list_detail" -> "游戏单"
        "common_collection" -> "通用合集"
        else -> ""
    }

    private fun bindCard(
        itemData: HomeItemData,
        homeSlideCardItemBinding: HomeSlideCardItemBinding,
        homeSubSlide: HomeSubSlide,
        basicExposureSource: List<ExposureSource>,
        position: Int
    ) {
        val cardCv = homeSlideCardItemBinding.root
        val cardContainer = homeSlideCardItemBinding.cardContainer
        val cardIv = homeSlideCardItemBinding.cardIv
        val backgroundGroup = homeSlideCardItemBinding.backgroundGroup
        val titleTv = homeSlideCardItemBinding.titleTv
        val descTv = homeSlideCardItemBinding.descTv
        val textContainer = homeSlideCardItemBinding.textContainer
        val countTv = homeSlideCardItemBinding.countTv
        val labelIv = homeSlideCardItemBinding.labelIv
        val gameIconStackIv1 = homeSlideCardItemBinding.gameIconStackIv1
        val gameIconStackIv2 = homeSlideCardItemBinding.gameIconStackIv2
        val gameIconStackIv3 = homeSlideCardItemBinding.gameIconStackIv3
        val gameIconStackGroup = listOf(gameIconStackIv1, gameIconStackIv2, gameIconStackIv3)
        val gameIconIv1 = homeSlideCardItemBinding.gameIconIv1
        val gameIconIv2 = homeSlideCardItemBinding.gameIconIv2
        val gameIconIv3 = homeSlideCardItemBinding.gameIconIv3
        val gameIconGroup = listOf(gameIconIv1, gameIconIv2, gameIconIv3)

        titleTv.text = homeSubSlide.title
        titleTv.setTextColor(R.color.text_title.toColor(titleTv.context))
        descTv.setTextColor(R.color.text_subtitle.toColor(descTv.context))

        val exposureEvent = ExposureEvent.createEventWithSourceConcat(
            gameEntity = GameEntity().apply {
                sequence = position
                outerSequence = viewModel.refreshCount
            },
            basicSource = basicExposureSource,
            source = listOf(
                ExposureSource(
                    "右侧卡片",
                    "${homeSubSlide.cardId} - ${getCardTypeChinese(homeSubSlide.cardType)}"
                )
            )
        )
        itemData.exposureEventList?.add(exposureEvent)

        when (homeSubSlide.cardType) {
            "column",
            "column_test_v2",
            "server",
            "game_explore" -> {
                titleTv.visibility = View.VISIBLE
                descTv.visibility = View.VISIBLE
                countTv.visibility = View.GONE
                labelIv.visibility = View.GONE
                backgroundGroup.visibility = View.GONE
                gameIconStackGroup.forEach { it.isVisible = homeSubSlide.cardData.games.isNotEmpty() }
                gameIconGroup.forEach { it.visibility = View.GONE }

                descTv.text = homeSubSlide.cardDesc
                if (homeSubSlide.cardData.games.size == 1) {
                    gameIconStackIv2.visibility = View.GONE
                    gameIconStackIv1.visibility = View.GONE
                }
                if (homeSubSlide.cardData.games.size == 2) {
                    gameIconStackIv1.visibility = View.GONE
                }
                homeSubSlide.cardData.games.take(3).forEachIndexed { index, gameEntity ->
                    when (index) {
                        0 -> gameIconStackIv3.displayGameIcon(gameEntity, true)
                        1 -> gameIconStackIv2.displayGameIcon(gameEntity, true)
                        2 -> gameIconStackIv1.displayGameIcon(gameEntity, true)
                    }
                }
                ConstraintSet().apply {
                    clone(cardContainer)
                    clear(textContainer.id, ConstraintSet.TOP)
                    clear(textContainer.id, ConstraintSet.BOTTOM)
                    connect(textContainer.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP)
                    connect(textContainer.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
                }.applyTo(cardContainer)
            }
            "game_list_detail" -> {
                titleTv.visibility = View.VISIBLE
                descTv.visibility = View.GONE
                backgroundGroup.visibility = View.GONE
                gameIconStackGroup.forEach { it.visibility = View.GONE }
                gameIconGroup.forEach { it.isVisible = homeSubSlide.cardData.games.isNotEmpty() }

                if (homeSubSlide.cardData.games.size == 1) {
                    gameIconIv2.visibility = View.GONE
                    gameIconIv3.visibility = View.GONE
                }
                if (homeSubSlide.cardData.games.size == 2) {
                    gameIconIv3.visibility = View.GONE
                }
                homeSubSlide.cardData.games.take(3).forEachIndexed { index, gameEntity ->
                    when (index) {
                        0 -> {
                            gameIconIv1.displayGameIcon(gameEntity, true)
                            gameIconIv1.setOnClickListener {
                                com.gh.common.util.NewFlatLogUtils.logRightSideCardClick(
                                    homeSubSlide,
                                    viewModel.refreshCount,
                                    "游戏"
                                )
                                GameDetailActivity.startGameDetailActivity(
                                    binding.root.context,
                                    gameEntity.id,
                                    BaseActivity.mergeEntranceAndPath("新首页", "右侧卡片"),
                                    exposureEvent
                                )
                            }
                        }
                        1 -> {
                            gameIconIv2.displayGameIcon(gameEntity, true)
                            gameIconIv2.setOnClickListener {
                                com.gh.common.util.NewFlatLogUtils.logRightSideCardClick(
                                    homeSubSlide,
                                    viewModel.refreshCount,
                                    "游戏"
                                )
                                GameDetailActivity.startGameDetailActivity(
                                    binding.root.context,
                                    gameEntity.id,
                                    BaseActivity.mergeEntranceAndPath("新首页", "右侧卡片"),
                                    exposureEvent
                                )
                            }
                        }
                        2 -> {
                            gameIconIv3.displayGameIcon(gameEntity, true)
                            gameIconIv3.setOnClickListener {
                                com.gh.common.util.NewFlatLogUtils.logRightSideCardClick(
                                    homeSubSlide,
                                    viewModel.refreshCount,
                                    "游戏"
                                )
                                GameDetailActivity.startGameDetailActivity(
                                    binding.root.context,
                                    gameEntity.id,
                                    BaseActivity.mergeEntranceAndPath("新首页", "右侧卡片"),
                                    exposureEvent
                                )
                            }
                        }
                    }
                }
                countTv.isVisible = homeSubSlide.cardData.gameTotal.game > 3
                countTv.typeface = Typeface.createFromAsset(countTv.context.assets, "fonts/d_din_bold_only_number.ttf")
                countTv.text = "+${homeSubSlide.cardData.gameTotal.game - 3}"
                labelIv.isVisible = homeSubSlide.cardData.stamp.isNotEmpty()
                labelIv.setImageDrawable(
                    when (homeSubSlide.cardData.stamp) {
                        "official" -> R.drawable.label_official.toDrawable(labelIv.context)
                        "special_choice" -> R.drawable.label_premium.toDrawable(labelIv.context)
                        else -> null
                    }
                )
                ConstraintSet().apply {
                    clone(cardContainer)
                    clear(textContainer.id, ConstraintSet.TOP)
                    clear(textContainer.id, ConstraintSet.BOTTOM)
                    connect(
                        textContainer.id,
                        ConstraintSet.TOP,
                        ConstraintSet.PARENT_ID,
                        ConstraintSet.TOP,
                        8F.dip2px()
                    )
                    if (homeSubSlide.cardData.stamp.isEmpty()) {
                        clear(countTv.id, ConstraintSet.START)
                        connect(countTv.id, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END, 10F.dip2px())
                    } else {
                        clear(countTv.id, ConstraintSet.END)
                        connect(countTv.id, ConstraintSet.START, gameIconIv3.id, ConstraintSet.END, 4F.dip2px())
                    }
                }.applyTo(cardContainer)
            }
            "column_collection", "common_collection" -> {
                titleTv.visibility = View.VISIBLE
                descTv.visibility = View.VISIBLE
                countTv.visibility = View.GONE
                labelIv.visibility = View.GONE
                backgroundGroup.visibility = View.VISIBLE
                gameIconStackGroup.forEach { it.visibility = View.GONE }
                gameIconGroup.forEach { it.visibility = View.GONE }
                descTv.text = homeSubSlide.cardDesc
                // 防止重复加载图片导致闪烁
                if (homeSubSlide.image != cardIv.getTag(R.string.tag_img_url_id)) {
                    ImageUtils.display(cardIv, homeSubSlide.image, false, AlphaGradientProcess())
                    cardIv.setTag(R.string.tag_img_url_id, homeSubSlide.image)
                }
                ConstraintSet().apply {
                    clone(cardContainer)
                    clear(textContainer.id, ConstraintSet.TOP)
                    clear(textContainer.id, ConstraintSet.BOTTOM)
                    connect(textContainer.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP)
                    connect(textContainer.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
                }.applyTo(cardContainer)
            }
        }

        cardCv.setOnClickListener {
            ExposureManager.log(
                ExposureEvent.createEventWithSourceConcat(
                    gameEntity = GameEntity().apply {
                        sequence = position
                        outerSequence = viewModel.refreshCount
                    },
                    basicSource = basicExposureSource,
                    source = listOf(
                        ExposureSource(
                            "右侧卡片",
                            "${homeSubSlide.cardId} - ${getCardTypeChinese(homeSubSlide.cardType)}"
                        )
                    ),
                    event = ExposureType.CLICK
                )
            )
            com.gh.common.util.NewFlatLogUtils.logRightSideCardClick(homeSubSlide, viewModel.refreshCount, "卡片")
            DirectUtils.directToLinkPage(cardCv.context, homeSubSlide.toLinkEntity(), "新首页", "右侧卡片", exposureEvent)
        }
    }

    private fun updateImmersiveColor(color: Int) {
        callback.invoke(color)
        val gradientDrawable = DrawableView.getGradientDrawable(
            color,
            R.color.background_white.toColor(binding.root.context), GradientDrawable.Orientation.TOP_BOTTOM, 0f
        )
        binding.placeholderView.background = gradientDrawable
    }
}