package de.sebse.fuplanner2.whiteboard

import android.content.Context
import com.android.volley.VolleyError
import com.beust.klaxon.JsonObject
import com.beust.klaxon.Parser
import de.sebse.fuplanner2.database.*
import de.sebse.fuplanner2.network.Requester
import de.sebse.fuplanner2.utils.UpdateResult
import de.sebse.fuplanner2.utils.pmap
import de.sebse.fuplanner2.utils.updateResultOf
import de.sebse.fuplanner2.worker.FetchResourceErrorType
import de.sebse.fuplanner2.worker.FetchResourceException


suspend fun Whiteboard.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>("announcement_collection")?.pmap { obj ->
            val id: String = obj.string("announcementId") ?: return@pmap null
            val title: String = obj.string("title") ?: ""
            val body: String = obj.string("body") ?: ""
            val createdOn: Long = obj.long("createdOn") ?: 0
            val createdBy: String = obj.string("creatorUserId") ?: ""
            val attachments: List<Attachment> = obj.array<JsonObject>("attachments")?.map attach@{
                Attachment(
                    it.string("url") ?: return@attach null,
                    it.string("name") ?: return@attach null,
                    it.string("type") ?: return@attach null
                )
            }?.filterNotNull() ?: 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
        if (statusCode == 401)
            throw FetchResourceException(FetchResourceErrorType.ERR_AUTHORIZATION, statusCode)
        throw FetchResourceException(FetchResourceErrorType.ERR_NETWORK_ERROR, statusCode)
    }
}