package de.sebse.fuplanner2.database

import android.content.Context
import androidx.navigation.NavController
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.ForeignKey.CASCADE
import androidx.room.Index
import androidx.room.PrimaryKey
import com.beust.klaxon.JsonObject
import de.sebse.fuplanner2.R
import de.sebse.fuplanner2.ui.notification.NotificationFragmentDirections
import de.sebse.fuplanner2.utils.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

@Entity(
    foreignKeys = [
        ForeignKey(onDelete = CASCADE, entity = User::class, parentColumns = ["uid"], childColumns = ["userId"])
    ],
    indices = [
        Index("userId"),
        Index("internalId", "moduleType", unique = true)
    ]
)
data class Course (
    @PrimaryKey(autoGenerate = true) var uid: Long? = null,
    val userId: Long,
    val lastRefreshed: Long,
    val isSummerSemester: Boolean,
    val year: Int?,
    val lvNumber: HashSet<String>,
    val title: String,
    val type: String,
    val description: String,
    val internalId: String,
    val moduleType: Int,
    val lecturers: List<Lecturer>
): Comparable<Course>, Updatable {
    override fun getIdentifier(): String =
        internalId

    override fun getHash(): Int =
        hashCodeOf(isSummerSemester, year, lvNumber, title, type, description)

    override fun getData(): JsonObject =
        JsonObject(mapOf("title" to title, "uid" to uid))

    override fun getNotificationEntityType(): Notifications.CourseUpdateEntity =
        Notifications.CourseUpdateEntity.COURSE

    override fun compareTo(other: Course): Int {
        (year ?: Int.MIN_VALUE).compareTo(other.year ?: Int.MIN_VALUE).let {
            if (it != 0) return it
            return other.isSummerSemester.compareTo(isSummerSemester)
        }
    }

    companion object : UpdatableCompanion {
        override fun notificationText(
            actCtx: Context,
            type: Notifications.CourseUpdateType,
            data: JsonObject
        ): CharSequence? = when (type) {
            Notifications.CourseUpdateType.REMOVED -> actCtx.getHtmlSpannedString(R.string.not_course_update_course_removed, data.string("title"))
            Notifications.CourseUpdateType.UPDATED -> actCtx.getHtmlSpannedString(R.string.not_course_update_course_updated, data.string("title"))
            Notifications.CourseUpdateType.ADDED -> actCtx.getHtmlSpannedString(R.string.not_course_update_course_added, data.string("title"))
        }

        override fun adapterText(
            actCtx: Context,
            type: Notifications.CourseUpdateType,
            data: JsonObject
        ): CharSequence? = when (type) {
            Notifications.CourseUpdateType.REMOVED -> actCtx.getHtmlSpannedString(R.string.adapter_course_update_course_removed, data.string("title"))
            Notifications.CourseUpdateType.UPDATED -> actCtx.getHtmlSpannedString(R.string.adapter_course_update_course_updated, data.string("title"))
            Notifications.CourseUpdateType.ADDED -> actCtx.getHtmlSpannedString(R.string.adapter_course_update_course_added, data.string("title"))
        }

        override fun adapterCallback(
            actCtx: Context,
            type: Notifications.CourseUpdateType,
            data: JsonObject,
            navController: NavController
        ): () -> Unit {
            return {
                GlobalScope.launch {
                    data.long("uid")
                        ?.let { AppDatabase.getInstance().courseDao().getCourseById2(it) }
                        ?.let {
                            withContext(Dispatchers.Main) {
                                navController.navigate(NotificationFragmentDirections.actionNavNotificationsToCourseDetails(it.uid!!, it.title))
                            }
                        }
                }
            }
        }
    }
}
