package de.kif.frontend

import de.kif.common.Message
import de.kif.common.MessageType
import de.kif.common.RepositoryType
import de.kif.frontend.repository.*
import de.westermann.kwebview.async
import org.w3c.dom.MessageEvent
import org.w3c.dom.WebSocket
import org.w3c.dom.events.Event
import kotlin.browser.window

class WebSocketClient() {
    private val url = "ws://${window.location.host}/"

    private lateinit var ws: WebSocket

    @Suppress("UNUSED_PARAMETER")
    private fun onOpen(event: Event) {
        console.log("Connected!")
    }

    private fun onMessage(messageEvent: MessageEvent) {
        val message = Message.parse(messageEvent.data?.toString() ?: "")

        for (handler in messageHandlers) {
            if (handler.repository == message.repository) {
                when (message.type) {
                    MessageType.CREATE -> handler.onCreate(message.id)
                    MessageType.UPDATE -> handler.onUpdate(message.id)
                    MessageType.DELETE -> handler.onDelete(message.id)
                }
            }
        }
    }

    @Suppress("UNUSED_PARAMETER")
    private fun onClose(event: Event) {
        console.log("Disconnected!")
        async(1000) {
            connect()
        }
    }

    @Suppress("UNUSED_PARAMETER")
    private fun onError(event: Event) {
        console.log("An error occurred!")
    }

    private fun connect() {
        ws = WebSocket(url)

        ws.onopen = this::onOpen
        ws.onmessage = this::onMessage
        ws.onclose = this::onClose
        ws.onerror = this::onError
    }

    private val messageHandlers: List<MessageHandler> = listOf(
        RoomRepository.handler,
        ScheduleRepository.handler,
        TrackRepository.handler,
        UserRepository.handler,
        WorkGroupRepository.handler,
        PostRepository.handler
    )

    init {
        connect()
    }
}

abstract class MessageHandler(val repository: RepositoryType) {
    abstract fun onCreate(id: Long)
    abstract fun onUpdate(id: Long)
    abstract fun onDelete(id: Long)
}
