package com.gh.gamecenter.home.custom.viewholder

import android.util.DisplayMetrics
import android.view.ViewGroup.LayoutParams
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearSmoothScroller
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnScrollListener
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.common.view.ScrollEventListener
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.databinding.RecyclerNotificationColumnBinding
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.home.custom.BannerInRecyclerController
import com.gh.gamecenter.home.custom.CustomPageViewModel
import com.gh.gamecenter.home.custom.adapter.NotificationColumnAdapter
import com.gh.gamecenter.home.custom.createExposureEvent
import com.gh.gamecenter.home.custom.eventlistener.CommonContentCollectionEventHelper
import com.gh.gamecenter.home.custom.model.CustomCommonContentCollectionItem
import com.gh.gamecenter.home.custom.model.CustomPageData
import com.gh.gamecenter.home.custom.model.CustomPageItem
import com.gh.gamecenter.home.custom.tracker.CommonContentCollectionTracker

/**
 * 通用内容合集-通知栏目
 */
class NotificationColumnViewHolder(
    viewModel: CustomPageViewModel,
    private val lifecycleOwner: LifecycleOwner,
    val binding: RecyclerNotificationColumnBinding
) : BaseCustomViewHolder(viewModel, binding.root) {

    private var isScrolling = false

    private var targetPosition = -1

    private val bannerController = BannerInRecyclerController {
        nextToPage()
    }

    override val childEventHelper by lazy {
        CommonContentCollectionEventHelper(viewModel)
    }

    private val adapter by lazy(LazyThreadSafetyMode.NONE) {
        NotificationColumnAdapter(itemView.context)
    }

    private val layoutManager by lazy(LazyThreadSafetyMode.NONE) {
        object : LinearLayoutManager(itemView.context) {
            override fun smoothScrollToPosition(
                recyclerView: RecyclerView?,
                state: RecyclerView.State?,
                position: Int
            ) {
                val linearSmoothScroller = object : LinearSmoothScroller(itemView.context) {
                    override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics): Float {
                        return MILLISECONDS_PER_INCH / displayMetrics.densityDpi
                    }
                }
                linearSmoothScroller.targetPosition = position
                startSmoothScroll(linearSmoothScroller)
            }
        }
    }

    private val scrollEventListener by lazy(LazyThreadSafetyMode.NONE) {
        ScrollEventListener(binding.rvNotification).apply {
            registerOnPageChangeCallback(object : OnPageChangeCallback() {
                override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
                    if (positionOffset > 0F) {
                        // position 代表的是正在移出屏幕的 itemView 的位置
                        layoutManager.findViewByPosition(position)?.alpha = 1 - positionOffset
                        layoutManager.findViewByPosition(position + 1)?.alpha = positionOffset
                    } else {
                        // position 代表的是屏幕中间的 itemView的位置
                        layoutManager.findViewByPosition(position)?.alpha = 1F
                    }
                }

                override fun onPageSelected(position: Int) {
                    (_item as? CustomCommonContentCollectionItem)?.selectedPosition = position
                }
            })
        }
    }

    /**
     * 有新的通知栏被隐藏，检查这里是否需要刷新
     */
    private val hiddenNotifiesObserver = Observer<HashMap<String, MutableSet<String>>> {
        val item = _item as CustomCommonContentCollectionItem
        val hiddenIds = it[item.data.id]
        val notifies = item.data.notifies
        val dataList = notifies.filterNot { notify ->
            hiddenIds?.contains(notify.id) == true
        }
        if (dataList.isNotEmpty()) {
            runOnIoThread(isLightWeightTask = true) {
                fillExposureInfo(dataList)
            }

            adapter.submitList(dataList)
        } else {
            setVisible(false)
        }
    }

    init {
        lifecycleOwner.lifecycle.addObserver(bannerController)
        binding.rvNotification.itemAnimator = null

        binding.itcvContainer.setOnClickListener {
            val item = _item
            if (!isScrolling && item is CustomCommonContentCollectionItem) {
                val childPosition = adapter.getDataPosition(item.selectedPosition)
                val notify = adapter.getItem(childPosition)
                childEventHelper.navigateToLinkPage(
                    notify.link,
                    "通知栏目",
                    notify.exposureEvent
                )
            }
        }

        binding.vClose.setOnClickListener {
            if (!isScrolling) {
                closeItem()
            }
        }
    }

    override fun bindView(item: CustomPageItem) {
        super.bindView(item)
        if (item is CustomCommonContentCollectionItem) {
            if (item.data.notifies.isEmpty()) {
                setVisible(false)
                return
            } else {
                setVisible(true)
            }

            if (binding.rvNotification.adapter == null) {
                binding.rvNotification.layoutManager = layoutManager
                binding.rvNotification.addOnScrollListener(scrollEventListener)
                binding.rvNotification.adapter = adapter
                binding.rvNotification.addOnScrollListener(object : OnScrollListener() {
                    override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                        isScrolling = newState != RecyclerView.SCROLL_STATE_IDLE
                    }
                })
            }
        }
    }

    override fun onViewAttach(parent: RecyclerView?) {
        viewModel.shareHiddenNotifications.observe(lifecycleOwner, hiddenNotifiesObserver)
        bannerController.onViewAttachedToWindow(parent)
        val selectedPosition = (_item as? CustomCommonContentCollectionItem)?.selectedPosition ?: 0
        if (targetPosition != -1 && targetPosition != selectedPosition) {
            binding.rvNotification.scrollToPosition(targetPosition)
        }
    }

    override fun onViewDetach(parent: RecyclerView?) {
        viewModel.shareHiddenNotifications.removeObserver(hiddenNotifiesObserver)
        bannerController.onViewDetachedFromWindow(parent)
    }

    private fun nextToPage() {
        if (adapter.isBanner) {
            val layoutManager = binding.rvNotification.layoutManager
            if (layoutManager is LinearLayoutManager) {
                val firstPosition = layoutManager.findFirstCompletelyVisibleItemPosition()
                if (firstPosition != -1) {
                    // 请注意，有可能smoothScrollToPosition正在执行滚动动画时，当前ViewHolder会调用onViewDetach，导致RecyclerView无法滚动到目标位置，所以这里需要先记录目标位置
                    // 当ViewHolder Detach之后，再次Attach时，检查targetPosition是否等于selectedPosition，如果不相等，说明发生了以上情况，需要再次调用scrollToPosition将RecyclerView滚动到指定位置
                    targetPosition = firstPosition + 1
                    binding.rvNotification.smoothScrollToPosition(targetPosition)
                }
            }
        }
    }

    private fun fillExposureInfo(dataList: List<CustomPageData.Notify>) {
        for ((index, notify) in dataList.withIndex()) {
            val item = _item as CustomCommonContentCollectionItem
            val gameEntity = if (notify.linkType == "game") {
                GameEntity(id = notify.linkId, name = notify.linkText)
            } else {
                GameEntity()
            }
            notify.exposureEvent = createExposureEvent(
                gameEntity.also {
                    it.sequence = index
                    it.outerSequence = _item.position
                },
                listOf(
                    ExposureSource(
                        "通用内容合集",
                        "${item.data.name}+${item.data.layoutChinese}+${item.data.id}"
                    ),
                    ExposureSource(
                        item.data.layoutChinese,
                        "${notify.id}"
                    )
                ),
                pageConfigure.exposureSourceList,
                index,
                _item.componentPosition,
                createTrackData(item)
            )
        }
    }

    private fun closeItem() {
        val selectedPosition = layoutManager.findFirstCompletelyVisibleItemPosition()
        if (selectedPosition != -1) {
            val item = adapter.getItem(selectedPosition)
            if (!item.isClosable) {
                return
            }
            (_item as? CustomCommonContentCollectionItem)?.let {
                val link = LinkEntity(link = item.linkId, type = item.linkType, text = item.linkText)
                CommonContentCollectionTracker(pageLocation).trackLinkContentCollectionClick(_item, link, "关闭通知")
                viewModel.hideNotificationItem(it.data.id, item.id)
            }
        }
    }

    private fun setVisible(isVisible: Boolean) {
        if (isVisible) {
            binding.root.goneIf(false)
            binding.root.updateLayoutParams {
                height = 80F.dip2px()
                width = LayoutParams.MATCH_PARENT
            }
        } else {
            binding.root.goneIf(true)
            binding.root.updateLayoutParams {
                height = 0
                width = LayoutParams.MATCH_PARENT
            }
        }
    }

    companion object {
        private const val MILLISECONDS_PER_INCH = 1000f
    }

}