package com.gh.gamecenter.search

import android.annotation.SuppressLint
import android.os.Handler
import android.os.Looper
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import androidx.viewpager2.widget.ViewPager2
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
import com.gh.gamecenter.common.view.ScaleIndicatorView
import com.gh.gamecenter.gamecollection.square.GameCollectionSquareFragment.Companion.BANNER_LOOP_TIME

/**
 *  轮播图控制器 适用于RecyclerView中显示轮播图
 *  1.当RecyclerView发生滚动时，暂停轮播
 *  2.当前页面处于非活跃状态，暂停轮播
 *  3.当前 item 滑出屏幕，暂停轮播
 */
class BannerController<T, VH : ViewHolder>(
    private val banner: ViewPager2,
    private val indicator: ScaleIndicatorView,
    createAdapter: () -> BannerAdapter<T, VH>
) : DefaultLifecycleObserver {

    private val handler = Handler(Looper.getMainLooper())

    private var isAttachToWindow = false
    private var isActive = false
    private var isParentScrolling = false

    private val adapter by lazy {
        createAdapter()
    }

    /**
     * 当列表开始滚动时，banner暂停轮播
     */
    private val onScrollListener = object : RecyclerView.OnScrollListener() {
        override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
            isParentScrolling = newState != RecyclerView.SCROLL_STATE_IDLE
            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                start()
            } else {
                pause()
            }
        }

        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            if(dy == 0){
                // 页面初始化
                start()
            }
        }
    }

    init {
        banner.registerOnPageChangeCallback(object : OnPageChangeCallback() {
            override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
                indicator.onPageScrolled(adapter.getDataPosition(position), positionOffset)
            }

            override fun onPageSelected(position: Int) {
                start()
            }
        })
    }

    fun bind(data: List<T>) {
        handler.removeCallbacksAndMessages(null)
        if (banner.adapter == null) {
            banner.adapter = adapter
        }
        adapter.submitList(data)
        if (adapter.isBanner) {
            banner.setCurrentItem(adapter.getInitPosition(), false)

            with(indicator) {
                pageSize = data.size
                notifyDataChanged()
            }
        }
    }

    fun onViewAttachedToWindow(parent: RecyclerView?) {
        isAttachToWindow = true
        parent?.addOnScrollListener(onScrollListener)
    }

    fun onViewDetachedFromWindow(parent: RecyclerView?) {
        isAttachToWindow = false
        pause()
        parent?.removeOnScrollListener(onScrollListener)
    }

    fun start() {
        if (adapter.isBanner && isActive && !isParentScrolling) {
            handler.removeCallbacks(nextPageRunner)
            handler.postDelayed(nextPageRunner, BANNER_LOOP_TIME)
        }
    }

    fun pause() {
        handler.removeCallbacksAndMessages(null)
    }

    private fun destroy() {
        handler.removeCallbacksAndMessages(null)
    }

    override fun onResume(owner: LifecycleOwner) {
        isActive = true
        if (isAttachToWindow) {
            start()
        }
    }

    override fun onPause(owner: LifecycleOwner) {
        isActive = false
        pause()
    }

    override fun onDestroy(owner: LifecycleOwner) {
        destroy()
    }

    private val nextPageRunner = object : Runnable {
        override fun run() {
            val position = banner.currentItem
            val itemCount = banner.adapter?.itemCount ?: 0
            if (position + 1 < itemCount) {
                banner.setCurrentItem(position + 1, true)
                handler.postDelayed(this, BANNER_LOOP_TIME)
            }
        }

    }

    abstract class BannerAdapter<T, VH : ViewHolder> : RecyclerView.Adapter<VH>() {

        private val dataList = arrayListOf<T>()

        open val isBanner:Boolean
            get() = dataCount > 0

        val dataCount: Int
            get() = dataList.size

        final override fun getItemCount(): Int =
            if (isBanner)  Int.MAX_VALUE else dataCount

        fun getDataPosition(position: Int): Int =
            if (isBanner)  position % dataCount else position


        fun getItem(position: Int): T = dataList[getDataPosition(position)]

        /**
         * 如果轮播图左右无限滚动，则初始化位置应该从中间开始
         */
        fun getInitPosition() =
            if (isBanner) {
                (Int.MAX_VALUE / 2) - (Int.MAX_VALUE / 2) % dataCount
            } else {
                0
            }

        @SuppressLint("NotifyDataSetChanged")
        fun submitList(data: List<T>?) {
            dataList.clear()
            data?.let(dataList::addAll)
            notifyDataSetChanged()
        }
    }
}