package de.kif.frontend.repository

import de.kif.common.ConstraintMap
import de.kif.common.Repository
import de.kif.common.RepositoryType
import de.kif.common.Serialization
import de.kif.common.model.Schedule
import de.kif.frontend.MessageHandler
import de.westermann.kobserve.event.EventHandler
import kotlinx.serialization.DynamicObjectParser
import kotlinx.serialization.list

object ScheduleRepository : Repository<Schedule> {

    val prefix = js("prefix")

    override val onCreate = EventHandler<Long>()
    override val onUpdate = EventHandler<Long>()
    override val onDelete = EventHandler<Long>()

    private val parser = DynamicObjectParser()

    override suspend fun get(id: Long): Schedule? {
        val json = repositoryGet("$prefix/api/schedule/$id") ?: return null
        return parser.parse(json, Schedule.serializer())
    }

    suspend fun getUpcoming(count: Int = 8): List<Schedule> {
        val json = repositoryGet("$prefix/api/schedules/upcoming?count=$count") ?: return emptyList()
        return parser.parse(json, Schedule.serializer().list)
    }

    override suspend fun create(model: Schedule): Long {
        return repositoryPost("$prefix/api/schedules", Serialization.stringify(Schedule.serializer(), model))
            ?: throw IllegalStateException("Cannot create model!")
    }

    override suspend fun update(model: Schedule) {
        if (model.id == null) throw IllegalStateException("Cannot update model which was not created!")
        repositoryPost("$prefix/api/schedule/${model.id}", Serialization.stringify(Schedule.serializer(), model))
    }

    override suspend fun delete(id: Long) {
        repositoryPost("$prefix/api/schedule/$id/delete")
    }

    override suspend fun all(): List<Schedule> {
        val json = repositoryGet("$prefix/api/schedules") ?: return emptyList()
        return parser.parse(json, Schedule.serializer().list)
    }

    val handler = object : MessageHandler(RepositoryType.SCHEDULE) {

        override fun onCreate(id: Long) = onCreate.emit(id)

        override fun onUpdate(id: Long) = onUpdate.emit(id)

        override fun onDelete(id: Long) = onDelete.emit(id)
    }

    suspend fun checkConstraints(): ConstraintMap {
        val json = repositoryGet("$prefix/api/constraints")
        return parser.parse(json, ConstraintMap.serializer())
    }

    suspend fun checkConstraintsFor(schedule: Schedule): ConstraintMap {
        val json = repositoryGet("$prefix/api/constraint/${schedule.id}")
        return parser.parse(json, ConstraintMap.serializer())
    }
}
