package com.gh.gamecenter.common.view

import android.content.Context
import android.util.AttributeSet
import android.view.*
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.gh.gamecenter.common.R
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.rxTimer
import com.gh.gamecenter.core.utils.DisplayUtils
import io.reactivex.disposables.Disposable
import kotlin.math.abs

/**
 * 横向可滑动控件
 */
class HorizontalScrollableView : LinearLayout {

    private var mDataList = ArrayList<Any>()
    private var currentPage = 0
    private var autoDurationTime = 6000L
    private var mRxTimer: Disposable? = null
    private var lastX: Float = 0F
    private var lastY: Float = 0F
    private var startX: Float = 0F
    private var startY: Float = 0F
    private val mTouchSlop = ViewConfiguration.get(context).scaledTouchSlop
    private lateinit var mIndicatorLayout: LinearLayout
    private lateinit var mViewPager2: ViewPager2
    private var mWidth = ViewGroup.LayoutParams.WRAP_CONTENT
    private var mHeight = ViewGroup.LayoutParams.WRAP_CONTENT

    private var mAutoScrollEnabled = true

    private var onPageSelectedAction: ((Int) -> Unit)? = null

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    init {
        initViews()
    }

    fun disableAutoScroll() {
        mAutoScrollEnabled = false
    }

    fun setFixedWidthAndHeightForViewPager2(widthInDp: Int, heightInDp: Int) {
        mWidth = widthInDp
        mHeight = heightInDp
        mViewPager2.layoutParams.apply {
            width = mWidth
            height = mHeight
        }
    }

    private fun initViews() {
        orientation = VERTICAL
        mViewPager2 = ViewPager2(context).apply {
            orientation = ViewPager2.ORIENTATION_HORIZONTAL
            registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
                override fun onPageSelected(position: Int) {
                    super.onPageSelected(position)
                    currentPage = position
                    if (mDataList.isNotEmpty()) {
                        slideIndicator(currentPage % mDataList.size)
                    }
                    onPageSelectedAction?.invoke(position)
                }
            })
        }
        val recyclerView = mViewPager2.getChildAt(0) as RecyclerView
        recyclerView.overScrollMode = RecyclerView.OVER_SCROLL_NEVER
        addView(mViewPager2)
        mIndicatorLayout = LinearLayout(context).apply {
            orientation = HORIZONTAL
            gravity = Gravity.CENTER
            val params = LayoutParams(LayoutParams.MATCH_PARENT, 12F.dip2px())
            params.topMargin = 4F.dip2px()
            params.leftMargin = 6F.dip2px()
            params.rightMargin = 6F.dip2px()
            layoutParams = params
            background = context.resources.getDrawable(R.drawable.background_shape_10p_black_radius_6)
        }
        addView(mIndicatorLayout)
    }

    fun start(
        datas: ArrayList<*>,
        startFromCenter: Boolean,
        newAdapter: RecyclerView.Adapter<*>,
        onPageSelectedAction: ((Int) -> Unit)? = null
    ) {
        if (datas.isEmpty()) throw IllegalArgumentException("列表不能为空")
        val adapter = mViewPager2.adapter
        this.onPageSelectedAction = onPageSelectedAction
        mDataList = datas as ArrayList<Any>
        if (adapter == null) {
            mViewPager2.adapter = newAdapter
        } else {
            adapter.notifyDataSetChanged()
        }
        currentPage = if (startFromCenter) getActualFirstPositionInCenter() else 0
        mViewPager2.setCurrentItem(currentPage, false)
        if (mDataList.size >= 1) {
            resetIndicator()
            autoPlay()
        }
    }

    private fun autoPlay() {
        if (mAutoScrollEnabled && mDataList.size > 1) {
            if (mRxTimer != null && !mRxTimer!!.isDisposed) {
                mRxTimer?.dispose()
                mRxTimer = null
            }
            mRxTimer = rxTimer(autoDurationTime) {
                slidePage()
            }
        }
    }

    private fun slidePage() {
        currentPage++
        mViewPager2.setCurrentItem(currentPage, true)
    }

    fun resumePage() {
        autoPlay()
    }

    fun pausePage() {
        if (mRxTimer != null && !mRxTimer!!.isDisposed) {
            mRxTimer?.dispose()
            mRxTimer = null
        }
    }

    fun resetIndicator() {
        mIndicatorLayout.removeAllViews()

        if (mDataList.size <= 1) {
            mIndicatorLayout.visibility = View.GONE
            return
        }

        mDataList.forEach { _ ->
            val view = View(context).apply {
                background = ContextCompat.getDrawable(context, R.drawable.selector_video_detail_ad_indicator)
                val params = LayoutParams(DisplayUtils.dip2px(4F), DisplayUtils.dip2px(4F))
                params.leftMargin = DisplayUtils.dip2px(2F)
                params.rightMargin = DisplayUtils.dip2px(2F)
                layoutParams = params
            }
            mIndicatorLayout.addView(view)
        }

        if (mDataList.isNotEmpty()) {
            slideIndicator(currentPage % mDataList.size)
        }
    }

    private fun slideIndicator(position: Int) {
        for (i in 0 until mIndicatorLayout.childCount) {
            val childAt = mIndicatorLayout.getChildAt(i)
            childAt.isSelected = i == position
        }
    }

    private fun getActualFirstPositionInCenter(): Int {
        if (mDataList.size == 1) return 0
        var index = Int.MAX_VALUE / 2
        if (index % mDataList.size != 0) {
            index -= (index % mDataList.size)
        }
        return index - 1
    }

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        val action = ev.action
        if (action == MotionEvent.ACTION_DOWN) {
            lastX = ev.rawX
            startX = lastX
            lastY = ev.rawY
            startY = lastY
        } else if (action == MotionEvent.ACTION_MOVE) {
            lastX = ev.rawX
            lastY = ev.rawY
            val distanceX = abs(lastX - startX)
            val distanceY = abs(lastY - startY)
            val disallowIntercept: Boolean = if (mViewPager2.orientation == ViewPager2.ORIENTATION_HORIZONTAL) {
                distanceX > mTouchSlop && distanceX > distanceY
            } else {
                distanceY > mTouchSlop && distanceY > distanceX
            }
            parent.requestDisallowInterceptTouchEvent(disallowIntercept)
        } else if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
            return abs(lastX - startX) > mTouchSlop || abs(lastY - startY) > mTouchSlop
        }
        return super.onInterceptTouchEvent(ev)
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        if (mRxTimer != null && !mRxTimer!!.isDisposed) {
            mRxTimer?.dispose()
            mRxTimer = null
        }
    }

    fun getAdDatas(): ArrayList<Any> {
        return mDataList
    }

}