package uz.mobiuz.mobiservice.dev.ui.sdk.card

import androidx.recyclerview.widget.DiffUtil
import com.hannesdorfmann.adapterdelegates4.ListDelegationAdapter
import uz.agr.sdk.core.entity.card.CardInfo
import uz.agr.sdk.coreui.ui.list.ProgressAdapterDelegate
import uz.agr.sdk.coreui.ui.list.ProgressItem
import uz.mobiuz.mobiservice.dev.utils.extensions.MultiBlock


class CardsListAdapter(
    private val hideSettingsIcon: Boolean,
) : ListDelegationAdapter<MutableList<Any>>() {

    private var listener: MultiBlock<CardInfo, Int>? = null

    init {
        items = mutableListOf()
        val delegateAdapter = CardDelegate(hideSettingsIcon)
        delegateAdapter.setOnClickListener { cardInfo, i ->
            listener?.invoke(cardInfo,i)
        }
        delegatesManager.addDelegate(delegateAdapter)
        delegatesManager.addDelegate(ProgressAdapterDelegate())
    }

    fun setData(cardsList: List<CardInfo>) {
        val oldData = items.toList()
        val progress = isProgress()

        items.clear()
        items.addAll(cardsList)
        items.addAll(cardsList)
        items.addAll(cardsList)
        items.addAll(cardsList)
        if (progress) items.add(ProgressItem())

        //yes, on main thread...
        DiffUtil
            .calculateDiff(DiffCallback(items, oldData), false)
            .dispatchUpdatesTo(this)
    }

    fun showProgress(isVisible: Boolean) {
        val oldData = items.toList()
        val currentProgress = isProgress()

        if (isVisible && !currentProgress) {
            items.add(ProgressItem())
            notifyItemInserted(items.lastIndex)
        } else if (!isVisible && currentProgress) {
            items.remove(items.last())
            notifyItemRemoved(oldData.lastIndex)
        }
    }

    private fun isProgress() = items.isNotEmpty() && items.last() is ProgressItem

    private inner class DiffCallback(
        private val newItems: List<Any>,
        private val oldItems: List<Any>
    ) : DiffUtil.Callback() {

        override fun getOldListSize() = oldItems.size
        override fun getNewListSize() = newItems.size

        override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
            val oldItem = oldItems[oldItemPosition]
            val newItem = newItems[newItemPosition]

            return if (newItem is CardInfo && oldItem is CardInfo) {
                newItem.id == oldItem.id
            } else {
                newItem is ProgressItem && oldItem is ProgressItem
            }
        }

        override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
            val oldItem = oldItems[oldItemPosition]
            val newItem = newItems[newItemPosition]

            return if (newItem is CardInfo && oldItem is CardInfo) {
                newItem.status == oldItem.status
                        && newItem.balance == oldItem.balance
            } else {
                true
            }
        }
    }

    fun setOnClickListener(block: MultiBlock<CardInfo, Int>) {
        listener = block
    }
}