package com.gh.gamecenter.home.test_v2

import android.view.MotionEvent
import android.view.View
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.core.view.postDelayed
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.ethanhua.skeleton.Skeleton
import com.ethanhua.skeleton.ViewSkeletonScreen
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
import com.gh.gamecenter.common.baselist.LoadStatus
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.DarkModeUtils
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.jumpToPositionForSmoothScroller
import com.gh.gamecenter.common.view.FixLinearLayoutManager
import com.gh.gamecenter.common.view.divider.PaddingDecoration
import com.gh.gamecenter.databinding.ItemHomeGameTestV2Binding
import com.gh.gamecenter.entity.HomeItemTestV2Entity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureSource
import com.gh.gamecenter.game.vertical.SpanCountPagerSnapHelper
import com.gh.gamecenter.home.ExposureItemData
import com.lightgame.utils.Utils
import kotlin.math.abs

/**
 * @author : liujiarui
 * date : 2023/3/3
 * description :首页-推荐tab-新游开测 item holder
 */
class HomeItemGameTestV2ViewHolder(
    private val mBinding: ItemHomeGameTestV2Binding,
    val viewModel: HomeGameTestV2ViewModel,
    private val lifecycleOwner: LifecycleOwner
) : BaseRecyclerViewHolder<Any>(mBinding.root) {

    private var mSkeletonView: ViewSkeletonScreen? = null

    private var mLastParseIndex = -1

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

    private var mHomePageGameList: List<GameEntity>? = null

    fun bindData(
        data: HomeItemTestV2Entity,
        exposureItemData: ExposureItemData,
        basicExposureSource: List<ExposureSource>,
        position: Int
    ) {
        //绑定时间轴数据
        bindTimePoint(data)
        //绑定新游开测推荐
        bindRecommend(data)
        //设置holder在父列表的位置
        (viewModel as? HomeGameTestV2DownloadStateUpdateHelper)?.setParentPosition(position)
        //绑定游戏列表
        bindGameList(viewModel, data, exposureItemData, basicExposureSource, position)
    }

    private fun bindGameList(
        viewModel: HomeGameTestV2ViewModel,
        data: HomeItemTestV2Entity,
        exposureItemData: ExposureItemData,
        basicExposureSource: List<ExposureSource>,
        position: Int
    ) {
        val context = mBinding.root.context
        val adapter = mBinding.recyclerView.adapter
        if (adapter is HomeGameTestV2GameListRvAdapter) {
            adapter.exposureItemData = exposureItemData
            //如果是刷新事件，直接刷新数据
            if (data.isRefresh) {
                setData(data)
                mBinding.recyclerView.scrollToPosition(0)
                Utils.log("HomeItemGameTestV2ViewHolder", "新游开测 bindGameList refresh")
            }
            //修复深色模式切换过程中，背景色不对的问题
            adapter.notifyItemRangeChanged(0, adapter.itemCount)
            val isDarkModeOn = DarkModeUtils.isDarkModeOn(context)
            if (isDarkModeOn) {
                mBinding.container.background = null
            } else {
                mBinding.container.setBackgroundResource(R.drawable.bg_test_v2_card_shadow)
            }
            mBinding.containerLl.background =
                ContextCompat.getDrawable(context, R.drawable.bg_item_game_test_v2)
            //如果是游戏屏蔽列表更新事件，这里比对现有的游戏列表，是否需要更新
            checkData(adapter, data)
            return
        }
        val spanCount = 3
        val gridLayoutManager = GridLayoutManager(context, spanCount, GridLayoutManager.HORIZONTAL, false)
        mBinding.recyclerView.layoutManager = gridLayoutManager
        val recyclerViewAdapter =
            HomeGameTestV2GameListRvAdapter(context, viewModel, basicExposureSource, position, exposureItemData)
        mBinding.recyclerView.adapter = recyclerViewAdapter
        mBinding.recyclerView.onFlingListener = null
        mBinding.recyclerView.isNestedScrollingEnabled = false
        mBinding.recyclerView.itemAnimator = null
        mBinding.recyclerView.clearOnScrollListeners()
        mBinding.recyclerView.addItemDecoration(HomeGameTestV2Decoration())
        val snapHelper = SpanCountPagerSnapHelper(spanCount, false)
        snapHelper.attachToRecyclerView(mBinding.recyclerView)
        viewModel.getDataListLiveData().observe(lifecycleOwner) { list ->
            recyclerViewAdapter.submitData(list)
        }
        viewModel.getGameListScrollLiveData().observe(lifecycleOwner) { p ->
            gridLayoutManager.scrollToPositionWithOffset(p, 0)
            //优化条目没有居中问题，因为上面没有触发snapHelper
            mBinding.recyclerView.postDelayed(100) {
                mBinding.recyclerView.jumpToPositionForSmoothScroller(p)
            }
        }
        viewModel.getLoadStateLiveData().observe(lifecycleOwner) {
            dispatchLoadState(it)
        }
        //列表滑动处理
        mBinding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)
                Utils.log("onScrollStateChanged: newState = $newState")
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    recyclerView.handler.removeCallbacksAndMessages(null)
                    recyclerView.postDelayed(300) { // 解决动画没结束时候条目和时间轴不对应问题
                        onRecyclerViewChanged(true)
                    }
                    recyclerView.post {
                        recyclerView.suppressLayout(false)
                    }
                } else if (newState == RecyclerView.SCROLL_STATE_SETTLING) {
                    recyclerView.suppressLayout(true)
                }
            }
        })
        mBinding.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)
                    }
                }
                return false
            }
        })
        setData(data)
    }

    //如果是游戏屏蔽列表更新事件，这里比对现有的游戏列表，是否需要更新
    private fun checkData(
        adapter: HomeGameTestV2GameListRvAdapter,
        data: HomeItemTestV2Entity
    ) {
        val oldData = mHomePageGameList
        val newData = mutableListOf<GameEntity>()
        data.data.forEach {
            it.games.forEach { game ->
                newData.add(game)
            }
        }
        if (oldData?.size != newData.size) {
            setData(data)
            adapter.notifyDataSetChanged()
            Utils.log("checkData: size not equal")
            return
        }
        for (i in oldData.indices) {
            if (oldData[i].id != newData[i].id) {
                setData(data)
                adapter.notifyDataSetChanged()
                Utils.log("checkData: id not equal")
                return
            }
        }
    }

    /**
     * 设置初始数据
     */
    private fun setData(data: HomeItemTestV2Entity) {
        //设置时间轴数据
        viewModel.setTimePoint(data.startPoint)
        //设置游戏列表占位数据
        viewModel.setDataCount(data.dataCount)
        //推荐列表显示今天的游戏列表后左侧剩余的游戏数量
        val recommendLeftSurplusNum = data.recommendLeftSurplusNum
        //绑定游戏列表数据
        viewModel.addGameList(
            list = data.data,
            timeType = data.timeType,
            pageId = data.pageId,
            action = HomeGameTestV2ViewModel.Action.getActionByCommand(data.action),
            firstIndex = recommendLeftSurplusNum,
            isRefresh = true,
            isSameTimeType = true
        )
        //数据填充完毕后滑动到推荐列表指定位置
        if (recommendLeftSurplusNum > 0) {
            mBinding.recyclerView.postDelayed(100) {
                val gridLayoutManager = mBinding.recyclerView.layoutManager as? GridLayoutManager
                gridLayoutManager?.scrollToPositionWithOffset(recommendLeftSurplusNum, 0)
                mBinding.recyclerView.postDelayed(100) {
                    mBinding.recyclerView.jumpToPositionForSmoothScroller(recommendLeftSurplusNum)
                }
            }
        }
        //记录老的首页游戏列表数据
        val oldData = mutableListOf<GameEntity>()
        data.data.forEach {
            it.games.forEach { game ->
                oldData.add(game)
            }
        }
        mHomePageGameList = oldData
    }

    /**
     * 列表滑动或者数据变更，分析第一个条目索引，决定是否加载数据
     */
    private fun onRecyclerViewChanged(isOnScroll: Boolean = true) {
        val recyclerView = mBinding.recyclerView
        val adapter = recyclerView.adapter as? HomeGameTestV2GameListRvAdapter ?: return
        val layoutManager = recyclerView.layoutManager as GridLayoutManager
        val firstVisiblePosition = layoutManager.findFirstVisibleItemPosition()
        Utils.log("onScrollStateChanged: firstVisiblePosition = $firstVisiblePosition")
        val firstVisibleItem = adapter.mDataList.getOrNull(firstVisiblePosition)
        //第一个完全可见的条目
        val firstCompletelyVisiblePosition = layoutManager.findFirstCompletelyVisibleItemPosition()
        val firstCompletelyVisibleItem =
            adapter.mDataList.getOrNull(firstCompletelyVisiblePosition)
        firstVisibleItem?.let {
            //通知时间轴变化
            val timeType = firstCompletelyVisibleItem?.timeType ?: it.timeType
            if (isOnScroll) {
                viewModel.onTimePointSelected(timeType)
            }
            val parsePosition = if (firstCompletelyVisiblePosition != -1) {
                firstCompletelyVisiblePosition
            } else {
                firstVisiblePosition
            }
            //分析分页加载动作
            if (parsePosition != mLastParseIndex) {
                viewModel.parseActionWithPosition(parsePosition)
                mLastParseIndex = parsePosition
                Utils.log("onScrollStateChanged: parseActionWithPosition = $parsePosition")
            }
            //曝光条目
            adapter.exposureItem(parsePosition)
        }
    }

    private fun dispatchLoadState(it: LoadStatus?) {
        when (it) {
            LoadStatus.LIST_LOADING -> {
                //mBinding.recyclerView.suppressLayout(true)
            }
            LoadStatus.INIT_LOADING -> {
                mBinding.recyclerView.isVisible = false
                mBinding.reuseNoConnection.reuseNoConnection.isVisible = false
                showSkeletonView(mBinding.recyclerView)
            }
            LoadStatus.INIT_LOADED,
            LoadStatus.LIST_OVER,
            LoadStatus.LIST_LOADED -> {
                mBinding.recyclerView.isVisible = true
                mBinding.recyclerView.suppressLayout(false)
                mBinding.reuseNoConnection.reuseNoConnection.isVisible = false
                mSkeletonView?.hide()
                //停顿一下再分析是否加载下一页
                mBinding.recyclerView.postDelayed(500) {
                    onRecyclerViewChanged(false)
                }
            }
            LoadStatus.LIST_FAILED,
            LoadStatus.INIT_FAILED -> {
                mBinding.recyclerView.isVisible = false
                mBinding.recyclerView.suppressLayout(false)
                mBinding.reuseNoConnection.reuseNoConnection.isVisible = true
                mBinding.reuseNoConnection.reuseNetworkErrorDescTv.isVisible = false
                mBinding.reuseNoConnection.connectionReloadTv.isVisible = false
                mSkeletonView?.hide()
            }
            else -> {
                mBinding.recyclerView.suppressLayout(false)
                if (mBinding.recyclerView.isVisible) return
                mBinding.recyclerView.isVisible = true
                mBinding.reuseNoConnection.reuseNoConnection.isVisible = false
                mSkeletonView?.hide()
            }
        }
    }

    private fun showSkeletonView(view: View) {
        if (mSkeletonView != null) {
            mSkeletonView?.hide()
            mSkeletonView = null
        }
        mSkeletonView = Skeleton.bind(view)
            .shimmer(true)
            .angle(Constants.SHIMMER_ANGLE)
            .color(R.color.skeleton_shimmer_color)
            .duration(Constants.SHIMMER_DURATION)
            .maskWidth(Constants.MASK_WIDTH)
            .gradientCenterColorWidth(Constants.GRADIENT_CENTER_COLOR_WIDTH)
            .apply {
                load(R.layout.item_game_test_v2_list_sheleton)
            }
            .show()
    }

    /**
     * 绑定时间轴数据
     */
    private fun bindTimePoint(data: HomeItemTestV2Entity) {
        val context = mBinding.timePointRv.context
        var adapter = mBinding.timePointRv.adapter
        val timePointList = data.startPoint.map { it.key }
        if (adapter is HomeGameTestV2TimePointRvAdapter) {
            adapter.data = timePointList
            adapter.notifyItemRangeChanged(0, timePointList.count())
            return
        }
        adapter = HomeGameTestV2TimePointRvAdapter(context, viewModel, timePointList)
        mBinding.timePointRv.layoutManager =
            FixLinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
        mBinding.timePointRv.adapter = adapter
        mBinding.timePointRv.onFlingListener = null
        mBinding.timePointRv.isNestedScrollingEnabled = false
        mBinding.timePointRv.itemAnimator = null
        viewModel.getTimePointLiveData().observe(lifecycleOwner) {
            val item = adapter.data
            val index = item.indexOf(it)
            if (index != -1) {
                mBinding.timePointRv.smoothScrollToPosition(index)
                adapter.selectPoint(index, false)
            }
        }
    }

    /**
     * 获取时间轴适配器
     */
    fun getTimeLineAdapter(): HomeGameTestV2TimePointRvAdapter? {
        return mBinding.timePointRv.adapter as? HomeGameTestV2TimePointRvAdapter
    }

    /**
     * 绑定新游开测推荐标签数据
     */
    private fun bindRecommend(data: HomeItemTestV2Entity) {
        val recommendList = data.recommendLabel
        if (recommendList.isEmpty()) {
            mBinding.labelRecommendRv.isVisible = false
            return
        }
        mBinding.labelRecommendRv.isVisible = true
        val context = mBinding.labelRecommendRv.context
        val adapter = mBinding.labelRecommendRv.adapter
        if (adapter is HomeGameTestV2RecommendRvAdapter) {
            adapter.data = data.recommendLabel
            adapter.notifyItemRangeChanged(0, data.recommendLabel.count())
            return
        }
        mBinding.labelRecommendRv.layoutManager =
            FixLinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
        mBinding.labelRecommendRv.adapter =
            HomeGameTestV2RecommendRvAdapter(context, recommendList, viewModel.location, viewModel.blockData)
        mBinding.timePointRv.onFlingListener = null
        mBinding.labelRecommendRv.isNestedScrollingEnabled = false
        mBinding.labelRecommendRv.addItemDecoration(
            PaddingDecoration(leftSide = 16F.dip2px(), rightSide = 16F.dip2px(), rightSpace = 8F.dip2px())
        )
    }
}