package de.sebse.fuplanner2.ui.notification

import android.view.View
import android.view.ViewGroup
import androidx.navigation.NavController
import androidx.paging.PagedListAdapter
import androidx.recyclerview.widget.DiffUtil
import com.beust.klaxon.JsonObject
import de.sebse.fuplanner2.database.*
import de.sebse.fuplanner2.ui.NotificationHolder
import de.sebse.fuplanner2.utils.Notifications
import de.sebse.fuplanner2.utils.timeAgoString
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch

class NotificationAdapter(val navController: NavController): PagedListAdapter<Notification, NotificationHolder>(NotificationDiffCallback()) {

    val notificationDao = AppDatabase.getInstance().notificationDao()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NotificationHolder {
        return NotificationHolder.invoke(parent)
    }

    override fun onBindViewHolder(holder: NotificationHolder, position: Int) {
        val notification = getItem(position)
        val actCtx = holder.itemView.context

        notification?.getJsonData()?.let { json ->
            when (notification.channelId) {
                Notifications.COURSE_UPDATE_CHANNEL_ID -> {
                    val updateType =
                        Notifications.CourseUpdateType.values[json.int(Notifications.COURSE_UPDATE_TYPE_KEY) ?: 0]
                    val entityType =
                        Notifications.CourseUpdateEntity.values[json.int(Notifications.COURSE_UPDATE_ENTITY_KEY) ?: 0]
                    val data = json.obj(Notifications.COURSE_UPDATE_DATA_KEY) ?: JsonObject()
                    val adapterText = when (entityType) {
                        Notifications.CourseUpdateEntity.COURSE -> Course
                        Notifications.CourseUpdateEntity.ANNOUNCEMENT -> Announcement
                        Notifications.CourseUpdateEntity.ASSIGNMENT -> TODO()
                        Notifications.CourseUpdateEntity.GRADE -> TODO()
                        Notifications.CourseUpdateEntity.RESOURCE -> TODO()
                        Notifications.CourseUpdateEntity.EVENT -> Event
                    }.adapterText(actCtx, updateType, data)
                    val adapterCallback = when (entityType) {
                        Notifications.CourseUpdateEntity.COURSE -> Course
                        Notifications.CourseUpdateEntity.ANNOUNCEMENT -> Announcement
                        Notifications.CourseUpdateEntity.ASSIGNMENT -> TODO()
                        Notifications.CourseUpdateEntity.GRADE -> TODO()
                        Notifications.CourseUpdateEntity.RESOURCE -> TODO()
                        Notifications.CourseUpdateEntity.EVENT -> Event
                    }.adapterCallback(actCtx, updateType, data, navController)
                    Pair(adapterText, adapterCallback)
                }
                else -> null
            }
        }?.let { (adapterText, adapterCallback) ->
            holder.string.text = adapterText
            holder.timestamp.text = notification.created.timeAgoString(actCtx)
            holder.itemView.setOnClickListener {
                adapterCallback()
                GlobalScope.launch {
                    notificationDao.setRead(notification.uid!!)
                }
            }
            holder.read.visibility = if (notification.read)
                    View.INVISIBLE
                else
                    View.VISIBLE

        } ?: run {
            holder.clear()
            holder.itemView.setOnClickListener(null)
            holder.read.visibility = View.INVISIBLE
        }
    }
}

class NotificationDiffCallback : DiffUtil.ItemCallback<Notification>() {

    override fun areItemsTheSame(oldItem: Notification, newItem: Notification): Boolean {
        return oldItem.uid == newItem.uid
    }

    override fun areContentsTheSame(oldItem: Notification, newItem: Notification): Boolean {
        return oldItem.data == newItem.data && oldItem.read == newItem.read
    }
}