package com.gh.gamecenter.home.test_v2

import android.graphics.Rect
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnScrollListener
import androidx.recyclerview.widget.RecyclerView.ViewHolder

/**
 * @author : liujiarui
 * date : 2023/3/13
 * description : RecyclerView 拓展,观察ViewHolder 可见状态和百分比
 * 目前只支持 LinearLayoutManager 和 GridLayoutManager(前者的子类)
 * 除了滑动不可见，还有页面切换不可见，锁屏不可见(暂时没有)
 */

fun interface OnViewHolderVisibleChangeListener<T : ViewHolder> {
    /**
     * 观察指定类型的ViewHolder在RecyclerView可见状态变化
     * @param position ViewHolder在RecyclerView 的索引
     * @param viewHolder 对象
     * @param isVisible 是否可见
     * @param visiblePercent 可见百分比
     */
    fun onViewHolderVisibleStateChanged(
        position: Int,
        viewHolder: T,
        isVisible: Boolean,
        visiblePercent: Float
    )

}

inline fun <reified T : ViewHolder, reified C : Class<T>> RecyclerView.addViewHolderWatcher(
    viewHolderClass: C,
    onViewHolderVisibleChangeListener: OnViewHolderVisibleChangeListener<T>
) {

    val onScrollListener = object : OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            super.onScrolled(recyclerView, dx, dy)
            watch(recyclerView)
        }

        fun watch(recyclerView: RecyclerView) {
            val layoutManager = recyclerView.layoutManager ?: return
            if (layoutManager !is LinearLayoutManager) return
            val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
            val lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition()
            val visibleHolderList =
                (firstVisibleItemPosition..lastVisibleItemPosition).map {
                    val holder = recyclerView.findViewHolderForAdapterPosition(it)
                    Pair(it, holder)
                }
            visibleHolderList.forEach {
                val p = it.first
                val v = it.second as? T
                if (v != null && v::class.java == viewHolderClass) {
                    val visiblePercent = v.itemView.getVisiblePercent()
                    val isVisible = visiblePercent > 0
                    onViewHolderVisibleChangeListener.onViewHolderVisibleStateChanged(
                        p, v, isVisible, visiblePercent
                    )
                }
            }
        }

        /**
         * 获取view的可见面积
         */
        private fun View.getVisiblePercent(): Float {
            if (!isShown) {
                return 0F
            }
            //计算可见面积
            val rect = Rect()
            val visibility = getLocalVisibleRect(rect)
            if (!visibility) return 0F
            val visibleArea = rect.width() * rect.height()
            val area = width * height
            return visibleArea * 1F / area
        }
    }

    viewTreeObserver.addOnGlobalLayoutListener {
        onScrollListener.watch(this)
    }
    addOnScrollListener(onScrollListener)
}