package com.gh.gamecenter.common.baselist

import android.annotation.SuppressLint
import android.content.Context
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.utils.safelyGetInRelease
import com.gh.gamecenter.common.utils.testChannelOnly
import com.gh.gamecenter.core.utils.ToastUtils
import com.lightgame.adapter.BaseRecyclerAdapter

abstract class DiffUtilAdapter<DataType>(context: Context) :
    BaseRecyclerAdapter<RecyclerView.ViewHolder>(context) {

    protected var mDataList = ArrayList<DataType>()

    @SuppressLint("StaticFieldLeak")
    fun submitList(updateData: List<DataType>?) {
        if (updateData.isNullOrEmpty()) {
            mDataList.clear()
            notifyDataSetChanged()
            return
        }

        // 若直接传 updateData 给 DiffUtils 可能因为 HomeViewModel 操作 updateData 这个列表而出现 IndexOutOfBounds 异常，
        // 这里用新的数组包裹原数据
        val originData = ArrayList(mDataList)
        val updateDataCopy = ArrayList(updateData)

        try {
            ListExecutor.workerExecutor.execute {
                val diffResult = DiffUtil.calculateDiff(object : DiffUtil.Callback() {
                    override fun getOldListSize(): Int {
                        return originData.size
                    }

                    override fun getNewListSize(): Int {
                        return updateDataCopy.size
                    }

                    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
                        val oldItem = originData.safelyGetInRelease(oldItemPosition)
                        val newItem = updateDataCopy.safelyGetInRelease(newItemPosition)
                        return areItemsTheSame(oldItem, newItem)
                    }

                    override fun areContentsTheSame(
                        oldItemPosition: Int,
                        newItemPosition: Int
                    ): Boolean {
                        val oldItem = originData.safelyGetInRelease(oldItemPosition)
                        val newItem = updateDataCopy.safelyGetInRelease(newItemPosition)
                        return areContentsTheSame(oldItem, newItem)
                    }
                })
                ListExecutor.uiExecutor.execute {
                    mDataList = updateDataCopy
                    diffResult.dispatchUpdatesTo(this@DiffUtilAdapter)
                }
            }
        } catch (e: IndexOutOfBoundsException) {
            testChannelOnly {
                ToastUtils.toast("DiffUtilAdapter 遇到数组越界异常，请检查")
            }
            mDataList = updateDataCopy
            notifyDataSetChanged()
        }
    }

    protected open fun areItemsTheSame(oldItem: DataType?, newItem: DataType?): Boolean {
        return oldItem == newItem
    }

    protected open fun areContentsTheSame(oldItem: DataType?, newItem: DataType?): Boolean {
        return oldItem == newItem
    }
}