package com.dlc.eboard.ui.widget

import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.rc.core.log.RcLog

/**
 * info
 *
 * @author ReiChin_
 */
class LooperLayoutManager(
    @RecyclerView.Orientation
    private val orientation: Int = RecyclerView.VERTICAL
) : RecyclerView.LayoutManager() {

    companion object {
        const val TAG = "LooperLayoutManager"
    }

    override fun generateDefaultLayoutParams() = RecyclerView.LayoutParams(
        ViewGroup.LayoutParams.WRAP_CONTENT,
        ViewGroup.LayoutParams.WRAP_CONTENT
    )

    override fun isAutoMeasureEnabled() = true

    override fun canScrollHorizontally() = orientation == RecyclerView.HORIZONTAL

    override fun canScrollVertically() = orientation == RecyclerView.VERTICAL

    override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State) {
        if (itemCount <= 0) {
            return
        }

        // preLayout主要支持动画，直接跳过
        if (state.isPreLayout) {
            return
        }
        // 将视图分离放入scrap缓存中，以准备重新对view进行排版
        detachAndScrapAttachedViews(recycler)
        var autalLength = 0
        for (i in 0 until itemCount) {
            //初始化，将在屏幕内的view填充
            val itemView = recycler.getViewForPosition(i)
            addView(itemView)
            //测量itemView的宽高
            measureChildWithMargins(itemView, 0, 0)

            val width = getDecoratedMeasuredWidth(itemView)
            val height = getDecoratedMeasuredHeight(itemView)
            //根据itemView的宽高进行布局
            autalLength += if (orientation == RecyclerView.VERTICAL) {
                layoutDecorated(itemView, 0, autalLength, width, autalLength + height)
                height
            } else {
                layoutDecorated(itemView, autalLength, 0, autalLength + width, height)
                width
            }

            //如果当前布局过的itemView的宽度或高度总和大于RecyclerView的宽（水平）或高（垂直），则不再进行布局
            if (orientation == RecyclerView.VERTICAL) {
                if (autalLength > getHeight()) {
                    break
                }
            } else {
                if (autalLength > getWidth()) {
                    break
                }
            }
        }
    }

    override fun scrollHorizontallyBy(
        dx: Int,
        recycler: RecyclerView.Recycler,
        state: RecyclerView.State
    ): Int {
        if (orientation == RecyclerView.VERTICAL) {
            return 0
        }
        //1.左右滑动的时候，填充子view
        val travl = fillHorizontal(dx, recycler, state)
        if (travl == 0) {
            return 0
        }

        //2.滚动
        offsetChildrenHorizontal(travl * -1)

        //3.回收已经离开界面的
        recyclerHorizontalHideView(dx, recycler, state)
        return travl
    }

    override fun scrollVerticallyBy(
        dy: Int,
        recycler: RecyclerView.Recycler,
        state: RecyclerView.State
    ): Int {
        if (orientation == RecyclerView.HORIZONTAL) {
            return 0
        }

        //1.上下滑动的时候，填充子view
        val travl = fillVertical(dy, recycler, state)
        if (travl == 0) {
            return 0
        }

        //2.滚动
        offsetChildrenVertical(travl * -1)

        //3.回收已经离开界面的
        recyclerVerticalHideView(dy, recycler, state)
        return travl
    }

    /**
     * 左右滑动的时候，填充
     */
    private fun fillHorizontal(
        dx: Int,
        recycler: RecyclerView.Recycler,
        state: RecyclerView.State
    ): Int {
        if (dx > 0) {
            //标注1.向左滚动
            val lastView = getChildAt(childCount - 1) ?: return 0
            val lastPos = getPosition(lastView)
            //标注2.可见的最后一个itemView完全滑进来了，需要补充新的
            if (lastView.right < width) {
                //标注3.判断可见的最后一个itemView的索引，
                // 如果是最后一个，则将下一个itemView设置为第一个，否则设置为当前索引的下一个
                val scrap = if (lastPos == itemCount - 1) {
                    recycler.getViewForPosition(0)
                } else {
                    recycler.getViewForPosition(lastPos + 1)
                }
                //标注4.将新的itemViewadd进来并对其测量和布局
                addView(scrap)
                measureChildWithMargins(scrap, 0, 0)
                val width = getDecoratedMeasuredWidth(scrap)
                val height = getDecoratedMeasuredHeight(scrap)
                val insetsWidth = width - scrap.measuredWidth
                layoutDecorated(
                    scrap, lastView.right + insetsWidth, 0,
                    lastView.right + width + insetsWidth, height
                )
                return dx
            }
        } else {
            //向右滚动
            val firstView = getChildAt(0) ?: return 0
            val firstPos = getPosition(firstView)
            if (firstView.left >= 0) {
                val scrap = if (firstPos == 0) {
                    recycler.getViewForPosition(itemCount - 1)
                } else {
                    recycler.getViewForPosition(firstPos - 1)
                }
                addView(scrap, 0)
                measureChildWithMargins(scrap, 0, 0)
                val width = getDecoratedMeasuredWidth(scrap)
                val height = getDecoratedMeasuredHeight(scrap)
                layoutDecorated(
                    scrap, firstView.left - width, 0,
                    firstView.left, height
                )
            }
        }
        return dx
    }

    /**
     * 上下滑动的时候，填充
     */
    private fun fillVertical(
        dy: Int,
        recycler: RecyclerView.Recycler,
        state: RecyclerView.State
    ): Int {
        if (dy > 0) {
            //标注1.向上滚动
            val lastView = getChildAt(childCount - 1) ?: return 0
            val lastPos = getPosition(lastView)
            //标注2.可见的最后一个itemView完全滑进来了，需要补充新的
            if (lastView.bottom < height) {
                //标注3.判断可见的最后一个itemView的索引，
                // 如果是最后一个，则将下一个itemView设置为第一个，否则设置为当前索引的下一个
                val scrap = if (lastPos == itemCount - 1) {
                    recycler.getViewForPosition(0)
                } else {
                    recycler.getViewForPosition(lastPos + 1)
                }
                //标注4.将新的itemViewadd进来并对其测量和布局
                addView(scrap)
                measureChildWithMargins(scrap, 0, 0)
                val width = getDecoratedMeasuredWidth(scrap)
                val height = getDecoratedMeasuredHeight(scrap)
                val insetsHeight = height - scrap.measuredHeight
                layoutDecorated(
                    scrap, 0, lastView.bottom + insetsHeight,
                    width, lastView.bottom + height + insetsHeight
                )
                return dy
            }
        } else {
            //向下滚动
            val firstView = getChildAt(0) ?: return 0
            val firstPos = getPosition(firstView)
            if (firstView.top >= 0) {
                val scrap = if (firstPos == 0) {
                    recycler.getViewForPosition(itemCount - 1)
                } else {
                    recycler.getViewForPosition(firstPos - 1)
                }
                addView(scrap, 0)
                measureChildWithMargins(scrap, 0, 0)
                val width = getDecoratedMeasuredWidth(scrap)
                val height = getDecoratedMeasuredHeight(scrap)
                layoutDecorated(
                    scrap, 0, firstView.top - height,
                    width, firstView.top
                )
            }
        }
        return dy
    }

    /**
     * 回收界面不可见的view
     */
    private fun recyclerHorizontalHideView(
        dx: Int,
        recycler: RecyclerView.Recycler,
        state: RecyclerView.State
    ) {
        for (i in 0 until childCount) {
            val view = getChildAt(i) ?: continue
            if (dx > 0) {
                //向左滚动，移除一个左边不在内容里的view
                if (view.right < 0) {
                    removeAndRecycleView(view, recycler)
                    RcLog.info("LooperLayoutManager 循环<<<: 移除 一个view  childCount=$childCount")
                }
            } else {
                //向右滚动，移除一个右边不在内容里的view
                if (view.left > width) {
                    removeAndRecycleView(view, recycler)
                    RcLog.info("LooperLayoutManager 循环>>>: 移除 一个view  childCount=$childCount")
                }
            }
        }
    }

    /**
     * 回收界面不可见的view
     */
    private fun recyclerVerticalHideView(
        dy: Int,
        recycler: RecyclerView.Recycler,
        state: RecyclerView.State
    ) {
        for (i in 0 until childCount) {
            val view = getChildAt(i) ?: continue
            if (dy > 0) {
                //向上滚动，移除一个上边不在内容里的view
                if (view.bottom < 0) {
                    removeAndRecycleView(view, recycler)
                    RcLog.info("LooperLayoutManager 循环∧∧∧：移除 一个view  childCount=$childCount")
                }
            } else {
                //向下滚动，移除一个下边不在内容里的view
                if (view.top > height) {
                    removeAndRecycleView(view, recycler)
                    RcLog.info("LooperLayoutManager 循环∨∨∨: 移除 一个view  childCount=$childCount")
                }
            }
        }
    }

}