package com.grkj.iscs.view.widget

import android.content.Context
import android.util.SparseArray
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView

class SnakeGridLayoutManager(context: Context, spanCount: Int) : GridLayoutManager(context, spanCount) {

    private val reverseOrderMap = SparseArray<Boolean>()

    override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State?) {
        // 清空之前的缓存
        reverseOrderMap.clear()

        // 调用父类的 onLayoutChildren 方法进行默认布局
        super.onLayoutChildren(recycler, state)

        // 获取所有可见的子视图
        for (i in 0 until childCount) {
            val view = getChildAt(i)
            val position = getPosition(view!!)

            // 计算当前项所在的行号
            val row = position / spanCount

            // 判断是否需要反转该行的排列顺序
            if (row % 2 != 0) {
                reverseOrderMap.put(position, true)
            }
        }

        // 重新布局子视图
        detachAndScrapAttachedViews(recycler!!)
        layoutInSnakeOrder(recycler, state)
    }

    private fun layoutInSnakeOrder(recycler: RecyclerView.Recycler, state: RecyclerView.State?) {
        var left = paddingLeft
        var top = paddingTop
        var right: Int
        var bottom: Int

        var row = 0
        var col = 0

        for (i in 0 until itemCount) {
            val isReverse = reverseOrderMap.get(i, false)

            if (isReverse) {
                col = spanCount - 1 - (i % spanCount)
            } else {
                col = i % spanCount
            }

            if (col == 0 && i > 0) {
                row++
                left = paddingLeft
                top += getHeightForPosition(i - 1) + verticalSpaceItemDecoration
            }

            val view = recycler.getViewForPosition(i)
            addView(view)

            measureChildWithMargins(view, 0, 0)

            right = left + getWidthForPosition(i)
            bottom = top + getHeightForPosition(i)

            layoutDecorated(view, left, top, right, bottom)

            left += getWidthForPosition(i) + horizontalSpaceItemDecoration
        }
    }

    private fun getWidthForPosition(position: Int): Int {
        return width / spanCount
    }

    private fun getHeightForPosition(position: Int): Int {
        return height / spanCount
    }

    companion object {
        private const val horizontalSpaceItemDecoration = 0
        private const val verticalSpaceItemDecoration = 0
    }
}