package com.gh.gamecenter.game.horizontal

import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
import com.gh.gamecenter.core.iinterface.IOffsetable
import com.gh.gamecenter.core.utils.TimeUtils
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.utils.tryCatchInRelease
import com.gh.gamecenter.R
import com.gh.gamecenter.common.view.FixLinearLayoutManager
import com.gh.gamecenter.databinding.GameHorizontalListBinding
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.entity.SubjectEntity

class GameHorizontalSlideListViewHolder(val binding: GameHorizontalListBinding) :
    BaseRecyclerViewHolder<GameEntity>(binding.root) {

    private var mScrollListener: RecyclerView.OnScrollListener? = null
    private var mLastScrolledPosition = 0 // 上次记录的最后滚动位置

    fun bindHorizontalSlideList(
        subjectEntity: SubjectEntity,
        offsetable: IOffsetable
    ): GameHorizontalSlideAdapter {
        val context = binding.root.context
        var subjectAdapter = binding.recyclerView.adapter
        binding.fakeRemarkLine.setBackgroundColor(R.color.btn_gray_light.toColor(context))
        if (subjectAdapter == null) {
            binding.recyclerView.setPadding(10F.dip2px(), 8F.dip2px(), 10F.dip2px(), 8F.dip2px())
            binding.recyclerView.layoutManager = FixLinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
            binding.recyclerView.clipToPadding = false
            subjectAdapter = GameHorizontalSlideAdapter(context, subjectEntity)
            (binding.recyclerView.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
            binding.recyclerView.adapter = subjectAdapter
            binding.recyclerView.setScrollingTouchSlop(RecyclerView.TOUCH_SLOP_PAGING)
            binding.recyclerView.isNestedScrollingEnabled = false

            if (subjectEntity.data?.firstOrNull()?.test?.testTime != null && mLastScrolledPosition == 0) {
                scrollToSpecificItemForTheFirstTime(subjectEntity)
            }
        } else {
            (subjectAdapter as GameHorizontalSlideAdapter).checkResetData(subjectEntity)

            // 上次记录的最后滚动位置与当前位置不一致，viewHolder 被复用了
            if (mLastScrolledPosition != adapterPosition) {
                val offset = offsetable.getOffset(adapterPosition)
                if (offset == 0) {
                    if (subjectEntity.data?.firstOrNull()?.test?.testTime != null && mLastScrolledPosition == 0) {
                        scrollToSpecificItemForTheFirstTime(subjectEntity)
                    } else {
                        binding.recyclerView.scrollToPosition(0)
                    }
                } else {
                    // 可能会因为上下复用数据变化而出现 IndexOutOfBoundsException 异常，毕竟有局部更新功能...
                    tryCatchInRelease {
                        binding.recyclerView.scrollBy(offset, offset)
                    }
                }
            }
        }

        showFakeRemarkLineIfNeeded(subjectEntity)

        if (mScrollListener == null) {
            mScrollListener = object : RecyclerView.OnScrollListener() {
                override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                    super.onScrollStateChanged(recyclerView, newState)

                    if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                        mLastScrolledPosition = adapterPosition
                        offsetable.updateOffset(adapterPosition, recyclerView.computeHorizontalScrollOffset())
                    }
                }
            }

            binding.recyclerView.addOnScrollListener(mScrollListener!!)
        }

        return subjectAdapter
    }

    private fun scrollToSpecificItemForTheFirstTime(subjectEntity: SubjectEntity) {
        val position = findTheLatestTestGamePosition(subjectEntity)
        binding.recyclerView.scrollToPosition(position)
    }

    /**
     * 获取游戏专题中 "今天/最靠近今天的一天（未来优先于过去）" 游戏的位置
     */
    private fun findTheLatestTestGamePosition(subjectEntity: SubjectEntity): Int {
        // first 是日期偏差， second 是 position
        var latestDayBeforeTodayPair = Pair(Int.MIN_VALUE, 0)
        var latestDayAfterTodayPair = Pair(Int.MAX_VALUE, 0)

        for ((index, game) in subjectEntity.data!!.withIndex()) {
            val testDayOffset = TimeUtils.getDaysOffset(game.test?.testTime ?: -999)
            if (testDayOffset == 0) {
                latestDayBeforeTodayPair = Pair(0, index)
                latestDayAfterTodayPair = Pair(0, index)
                break
            } else if (testDayOffset < 0) {
                if (latestDayBeforeTodayPair.first >= testDayOffset) {
                    latestDayBeforeTodayPair = Pair(testDayOffset, index)
                }
            } else if (testDayOffset > 0) {
                if (testDayOffset <= latestDayAfterTodayPair.first) {
                    latestDayAfterTodayPair = Pair(testDayOffset, index)
                }
            }
        }

        return if (latestDayAfterTodayPair.first != Int.MAX_VALUE) {
            latestDayAfterTodayPair.second
        } else {
            latestDayBeforeTodayPair.second
        }
    }

    /**
     * 根据是否存在备注确定是否要显示和怎么显示一条假的指示线
     */
    private fun showFakeRemarkLineIfNeeded(subjectEntity: SubjectEntity) {
        var shouldShowFirstRemark = false
        var shouldShowSecondRemark = false
        for (entity in subjectEntity.data!!) {
            if (!shouldShowFirstRemark && entity.assignRemark.firstLine.isNotEmpty()) shouldShowFirstRemark = true
            if (!shouldShowSecondRemark && entity.assignRemark.secondLine.isNotEmpty()) shouldShowSecondRemark = true
            if (shouldShowFirstRemark && shouldShowSecondRemark) break
        }

        if (shouldShowFirstRemark && subjectEntity.typeStyle != "star") {
            // 这里显示一条假的线供上层 recyclerView 列表使用，因为写在 item 里面很复杂
            binding.root.post {
                binding.fakeRemarkLine.layoutParams =
                    (binding.fakeRemarkLine.layoutParams as ConstraintLayout.LayoutParams).apply {
                        topMargin = getTopOfLineContainer(binding.recyclerView) + 2F.dip2px() // 这里加上的2F是点的边距
                    }
            }
            binding.fakeRemarkLine.visibility = View.VISIBLE
        } else {
            binding.fakeRemarkLine.visibility = View.GONE
        }
    }

    private fun getTopOfLineContainer(vg: ViewGroup): Int {
        var height = 0
        for (i in 0 until vg.childCount) {
            val v: View = vg.getChildAt(i)
            if (v is ConstraintLayout && v.id == R.id.lineContainer) {
                return v.top
            } else if (v is ViewGroup) {
                height = this.getTopOfLineContainer(v) + v.top
            }
        }
        return height
    }

}