package de.sebse.fuplanner2.blackboard

import android.content.Context
import com.android.volley.VolleyError
import com.beust.klaxon.JsonObject
import com.beust.klaxon.Parser
import de.sebse.fuplanner2.auth.FUAuthModule.Companion.REFRESH_FREQUENCY_COURSES_MILLIS
import de.sebse.fuplanner2.database.*
import de.sebse.fuplanner2.network.Requester
import de.sebse.fuplanner2.utils.*
import de.sebse.fuplanner2.worker.FetchResourceErrorType
import de.sebse.fuplanner2.worker.FetchResourceException


suspend fun Blackboard.getAnnouncements(ctx: Context, database: AppDatabase, user: User, course: Course): UpdateResult<Announcement> {
    if (!isAvailable(user)) return UpdateResult()
    if (course.moduleType != MODULE_TYPE) return UpdateResult()
    val courseId = course.uid ?: return UpdateResult()

    val requester = Requester(ctx)
    val stored = database.announcementDao().getAll2(courseId)

    try {val data = requester.get(
        FETCH_ANNOUNCEMENT_LIST.format(course.internalId),
        getCookies(user)
    )
        val json = Parser.default().parse(StringBuilder(data.body)) as JsonObject
        val new = json.array<JsonObject>("results")?.pmap { obj ->
            val id: String = obj.string("id") ?: return@pmap null
            val title: String = obj.string("title") ?: ""
            val body: String = obj.obj("body")?.string("rawText") ?: ""
            val createdOn: Long = obj.string("startDateRestriction")?.dateStringToLong("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") ?: 0
            val createdBy: String = obj.string("creatorUserId")?.let { lecturerUserId ->
                Cache.getCache(database, lecturerUserId, "Blackboard_Users", REFRESH_FREQUENCY_COURSES_MILLIS) {
                    requester.get(
                        FETCH_USER_DETAILS.format(lecturerUserId),
                        getCookies(user)
                    ).body
                }.let { Parser.default().parse(StringBuilder(it)) as JsonObject }
                .let {
                    val given = it.obj("name")?.string("given")
                    val family = it.obj("name")?.string("family")
                    if (given != null && family != null)
                        "$given $family"
                    else
                        null
                }
            } ?: ""
            val attachments: List<Attachment> = listOf()
            Announcement(null, courseId, System.currentTimeMillis(), id, title, body, createdOn, createdBy, attachments)
        }?.filterNotNull() ?: listOf()
        val result = updateResultOf(stored, new)
        database.announcementDao().run {
            delete(result.removed)
            upsert(result.values)
        }
        return result
    } catch (e: VolleyError) {
        val statusCode = e.networkResponse.statusCode
        throw FetchResourceException(FetchResourceErrorType.ERR_NETWORK_ERROR, statusCode)
    }
}