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

import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.hannesdorfmann.adapterdelegates4.ListDelegationAdapter
import uz.agr.mobiuz.model.Tuple2
import uz.agr.mobiuz.ui.global.list.DividerAdapterDelegate
import uz.agr.sdk.coreui.extension.formattedMoney
import uz.agr.sdk.coreui.ui.history.DividerItem
import uz.agr.sdk.coreui.ui.list.ProgressAdapterDelegate
import uz.agr.sdk.coreui.ui.list.ProgressItem
import uz.mobiuz.mobiservice.dev.model.Monitoring

class MonitoringAdapter : ListDelegationAdapter<MutableList<Any>>() {

    init {
        items = mutableListOf()
        delegatesManager.addDelegate(HistoryHeaderDelegate())
        delegatesManager.addDelegate(MonitoringDelegate())
        delegatesManager.addDelegate(DividerAdapterDelegate())
        delegatesManager.addDelegate(ProgressAdapterDelegate())
    }

    fun isHeaderItem(position: Int): Boolean = items[position] is Tuple2

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

        items.clear()
        var summa: Long = 0

        val hashMap = HashMap<String, String>()
        for (item in historyList) {
            val it = hashMap[item.date.toString()]
            summa -= item.amount
            if (it != null) {
                val i = (it.toLong() + summa).toString()
                hashMap[item.date.toString()] = i
            } else {
                hashMap[item.date.toString()] = "$summa"
            }
            summa = 0
        }

        var tempDate = ""
        for (item in historyList) {
            if (tempDate != item.date.toString()) {
                items.add(DividerItem())
                val value = hashMap[item.date.toString()]
                items.add(
                    Tuple2(
                        item.date.toString(),
                        ((value?.replaceRange(value.length - 2, value.length, "") ?: "0").toInt() * 100).formattedMoney(false) + " UZS"
                    )
                )
                tempDate = item.date.toString()
            }
            items.add(item)
        }
        if (items.isNotEmpty()) {
            items.add(DividerItem())
        }
        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

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int, payloads: MutableList<Any?>) {
        super.onBindViewHolder(holder, position, payloads)
    }

    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 Monitoring && oldItem is Monitoring) {
                newItem.id == oldItem.id
            } else if (newItem is Tuple2 && oldItem is Tuple2) {
                newItem.first == oldItem.first
            } else {
                (newItem is ProgressItem && oldItem is ProgressItem)
                        || (newItem is DividerItem && oldItem is DividerItem)
            }
        }

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

            return if (newItem is Monitoring && oldItem is Monitoring) {
                newItem.id == oldItem.id
                        && newItem.date == oldItem.date
                        && newItem.amount == oldItem.amount
                        && newItem.phone == oldItem.phone
                        && newItem.pan == oldItem.pan
            } else if (newItem is Tuple2 && oldItem is Tuple2) {
                newItem.first == oldItem.first
            } else {
                true
            }
        }
    }
}