package com.gh.gamecenter.home.custom.ui

import android.content.Context
import android.view.MotionEvent
import android.view.View
import androidx.core.graphics.ColorUtils
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.ScrollEventListener
import com.gh.gamecenter.common.view.TouchSlopRecyclerView
import com.gh.gamecenter.databinding.HomeSlideListCustomBinding
import com.gh.gamecenter.entity.HomeSlide
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.home.custom.BannerInRecyclerController
import com.gh.gamecenter.home.custom.adapter.CustomHomeSlideListAdapter
import splitties.views.verticalPadding
import kotlin.math.abs

/**
 * 通用内容合集-轮播banner
 * ui逻辑封装，方便多个地方复用
 */
class CommonContentHomeSLideListUi(
    private val binding: HomeSlideListCustomBinding,
    lifecycleOwner: LifecycleOwner,
    private val listener: OnCommonHomeSlideListEventListener
) {

    private val context: Context
        get() = binding.root.context

    private var _slideList: List<HomeSlide>? = null

    private var _currentDataPosition = 0
    private var _itemPosition = 0

    private var mLastX: Int = 0
    private var mLastY: Int = 0

    private val layoutManager by lazy {
        LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
    }

    private val snapHelper by lazy {
        PagerSnapHelper()
    }

    private val scrollEventListener by lazy {
        ScrollEventListener(binding.recyclerView)
    }

    private val adapter by lazy {
        CustomHomeSlideListAdapter(
            context,
            snapHelper,
            layoutManager,
            false,
            object : CustomHomeSlideListAdapter.OnEventListener {
                override fun navigateToGameDetailPage(
                    actualPosition: Int,
                    game: GameEntity,
                    text: String,
                    link: LinkEntity?
                ) {
                    listener.navigateToGameDetailPage(actualPosition, game, text, link)
                }

                override fun navigateToLinkPage(link: LinkEntity, text: String, exposureEvent: ExposureEvent?) {
                    listener.navigateToLinkPage(link, text, exposureEvent)
                }
            })
    }

    private val bannerController = BannerInRecyclerController {
        adapter.scrollToNextPage()
    }

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

    fun bind(slideList: List<HomeSlide>, position: Int) {
        _itemPosition = position
        if (binding.recyclerView.adapter == null) {
            binding.recyclerView.layoutManager = layoutManager
            binding.recyclerView.adapter = adapter

            snapHelper.attachToRecyclerView(binding.recyclerView)
            binding.recyclerView.addOnItemTouchListener(object : RecyclerView.SimpleOnItemTouchListener() {
                override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
                    val x = e.x.toInt()
                    val y = e.y.toInt()

                    when (e.action) {
                        MotionEvent.ACTION_DOWN -> {
                            mLastX = e.x.toInt()
                            mLastY = e.y.toInt()
                            rv.parent.parent.requestDisallowInterceptTouchEvent(true)
                        }

                        MotionEvent.ACTION_UP -> rv.parent.parent.requestDisallowInterceptTouchEvent(
                            false
                        )

                        MotionEvent.ACTION_MOVE -> {
                            val deltaX: Int = x - mLastX
                            val deltaY: Int = y - mLastY
                            val isHorizontalScroll = abs(deltaX) > abs(deltaY)
                            rv.parent.parent.requestDisallowInterceptTouchEvent(isHorizontalScroll)
                        }
                    }

                    val isStop =
                        e.action == MotionEvent.ACTION_DOWN || e.action == MotionEvent.ACTION_MOVE
                    if (isStop) bannerController.pause() else bannerController.start()

                    val touchSlopRecyclerView = binding.recyclerView.parent.parent
                    if (touchSlopRecyclerView is TouchSlopRecyclerView) {
                        touchSlopRecyclerView.touchSlopEnabled = isStop
                    } else throwExceptionInDebug("TouchSlopRecyclerView not found")
                    return false
                }
            })

            binding.recyclerView.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
                requestTransform()
            }

            binding.recyclerView.addOnScrollListener(scrollEventListener.apply {
                registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
                    override fun onPageScrollStateChanged(state: Int) {
                        super.onPageScrollStateChanged(state)

                        if (state == RecyclerView.SCROLL_STATE_IDLE) {
                            bannerController.start()
                        } else {
                            bannerController.pause()
                        }

                        if (scrollState == RecyclerView.SCROLL_STATE_IDLE) {
                            val view = snapHelper.findSnapView(layoutManager)
                            var curPosition = 0
                            if (view != null) {
                                curPosition = adapter.getDataPosition(layoutManager.getPosition(view))
                                _currentDataPosition = curPosition
                            }
                            listener.updateImmersiveColor(
                                adapter.dataList.safelyGetInRelease(curPosition)?.placeholderColor?.hexStringToIntColor()
                                    ?: com.gh.gamecenter.common.R.color.ui_surface.toColor(binding.root.context)
                            )
                        }
                    }

                    override fun onPageSelected(position: Int) {
                        _currentDataPosition = adapter.getDataPosition(position)
                    }

                    override fun onPageScrolled(
                        position: Int,
                        positionOffset: Float,
                        positionOffsetPixels: Int
                    ) {
                        val currentPosition = adapter.getDataPosition(position)
                        val nextPosition = adapter.getDataPosition(position + 1)
                        _currentDataPosition = currentPosition

                        val currentColor =
                            adapter.dataList.getOrNull(currentPosition)?.placeholderColor?.hexStringToIntColor()
                                ?: com.gh.gamecenter.common.R.color.ui_surface.toColor(binding.root.context)
                        val nextColor =
                            adapter.dataList.getOrNull(nextPosition)?.placeholderColor?.hexStringToIntColor()
                                ?: currentColor

                        val colorInBetween =
                            ColorUtils.blendARGB(currentColor, nextColor, positionOffset)

                        transformPage(position, positionOffset)
                        listener.updateImmersiveColor(colorInBetween)
                    }
                })
            })
            adapter.submitList(slideList, true)
        } else {
            if (_slideList != slideList) {
                adapter.checkResetData(slideList)
            }

        }

        _slideList = slideList
        val currentPosition = adapter.getInitPosition() + _currentDataPosition
        layoutManager.scrollToPosition(currentPosition)

        val dataPosition = adapter.getDataPosition(currentPosition)
        listener.updateImmersiveColor(
            slideList.getOrNull(dataPosition)?.placeholderColor?.hexStringToIntColor()
                ?: com.gh.gamecenter.common.R.color.ui_surface.toColor(binding.root.context)
        )
        bannerController.start()
    }

    private fun requestTransform() {
        val relativePosition: Double = scrollEventListener.relativeScrollPosition
        val position = relativePosition.toInt()
        val positionOffset = (relativePosition - position).toFloat()
        transformPage(position, positionOffset)
    }

    private fun transformPage(position: Int, positionOffset: Float) {
        val transformOffset = -positionOffset

        for (i in 0 until layoutManager.childCount) {
            val view: View = layoutManager.getChildAt(i) ?: return
            val currPos: Int = layoutManager.getPosition(view)
            val viewOffset = transformOffset + (currPos - position)
            val scaleY = when {
                viewOffset <= -1 -> {
                    0.9f
                }

                viewOffset < 0 -> {
                    (1 + viewOffset) * 0.1f + 0.9f
                }

                viewOffset < 1 -> {
                    (1 - viewOffset) * 0.1f + 0.9f
                }

                else -> {
                    0.9f
                }
            }
            view.scaleY = scaleY
        }
    }

    fun onViewAttach(parent: RecyclerView?) {
        bannerController.onViewAttachedToWindow(parent)

    }

    fun onViewDetach(parent: RecyclerView?) {
        bannerController.onViewDetachedFromWindow(parent)
    }

    fun updateWhenTopVisibleItemCountChanged(isFirst: Boolean) {
        val paddingVertical = if (isFirst) {
            8f.dip2px()
        } else {
            16f.dip2px()
        }
        binding.recyclerView.verticalPadding = paddingVertical

        val dataList = adapter.dataList
        val currentPosition = if (_currentDataPosition == -1) {
            adapter.getInitPosition()
        } else {
            _currentDataPosition
        }
        val dataPosition = adapter.getDataPosition(currentPosition)
        listener.updateImmersiveColor(
            dataList.getOrNull(dataPosition)?.placeholderColor?.hexStringToIntColor()
                ?: com.gh.gamecenter.common.R.color.ui_surface.toColor(binding.root.context)
        )
    }

    interface OnCommonHomeSlideListEventListener {
        fun navigateToLinkPage(link: LinkEntity, text: String, exposureEvent: ExposureEvent?)

        fun navigateToGameDetailPage(position: Int, game: GameEntity, text: String, link: LinkEntity?)

        fun updateImmersiveColor(color: Int)
    }
}