package com.gh.gamecenter.common.view

import android.view.View
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.SnapHelper
import androidx.viewpager2.widget.ViewPager2
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min

class PageControllerAdapter(
    private val recyclerView: RecyclerView,
    private val snapHelper: SnapHelper,
    private val scrollEventListener: ScrollEventListener,
) : ViewPager2.OnPageChangeCallback() {

    private var mCurrentItem: Int = 0

    val currentItemDataSetChangeObserver: RecyclerView.AdapterDataObserver =
        object : RecyclerView.AdapterDataObserver() {
            override fun onChanged() {
                scrollEventListener.notifyDataSetChangeHappened()
            }

            override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {
                onChanged()
            }

            override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
                onChanged()
            }
        }

    override fun onPageSelected(position: Int) {
        if (mCurrentItem != position) {
            mCurrentItem = position
        }
    }

    override fun onPageScrollStateChanged(newState: Int) {
        if (newState == ViewPager2.SCROLL_STATE_IDLE) {
            updateCurrentItem()
        }
    }

    var currentItem: Int
        set(value) { setCurrentItem(value) }
        get() = mCurrentItem

    fun setCurrentItem(position: Int, smoothScroll: Boolean = true) {
        setCurrentItemInternal(position, smoothScroll)
    }

    private fun setCurrentItemInternal(item: Int, smoothScroll: Boolean) {
        var currentItem = item
        val adapter: RecyclerView.Adapter<*>? = recyclerView.adapter
        if (adapter == null || adapter.itemCount <= 0) {
            return
        }

        currentItem = max(currentItem.toDouble(), 0.0).toInt()
        currentItem = min(currentItem.toDouble(), (adapter.itemCount - 1).toDouble()).toInt()

        if (currentItem == mCurrentItem && scrollEventListener.isIdle) {
            return
        }
        if (currentItem == mCurrentItem && smoothScroll) {
            return
        }

        var previousItem = mCurrentItem.toDouble()
        mCurrentItem = currentItem

        if (!scrollEventListener.isIdle) {
            previousItem = scrollEventListener.relativeScrollPosition
        }

        scrollEventListener.notifyProgrammaticScroll(currentItem, smoothScroll)
        if (!smoothScroll) {
            recyclerView.scrollToPosition(currentItem)
            return
        }

        if (abs(currentItem - previousItem) > 3) {
            recyclerView.scrollToPosition(if (currentItem > previousItem) currentItem - 3 else currentItem + 3)
            recyclerView.post { recyclerView.smoothScrollToPosition(currentItem) }
        } else {
            recyclerView.smoothScrollToPosition(currentItem)
        }
    }

    private fun updateCurrentItem() {
        val snapView: View = snapHelper.findSnapView(recyclerView.layoutManager) ?: return
        val snapPosition: Int = recyclerView.layoutManager?.getPosition(snapView) ?: return

        if (snapPosition != mCurrentItem && scrollEventListener.scrollState == ViewPager2.SCROLL_STATE_IDLE) {
            scrollEventListener.dispatchSelected(snapPosition)
        }
    }
}