package tech.nut.nut_player_android

import tech.nut.player.model.BufferingState
import tech.nut.player.model.ContentLoadingState
import tech.nut.player.model.ErrorState
import tech.nut.player.model.FinishState
import tech.nut.player.model.NutEvent
import tech.nut.player.model.NutPlayerState
import tech.nut.player.model.OnPlayerStateChange
import tech.nut.player.model.PauseState
import tech.nut.player.model.PlayState
import tech.nut.player.model.ReadyState
import tech.nut.player.model.plugin.NutEventListener
import tech.nut.player.model.plugin.NutPlugin
import kotlin.reflect.KClass

class NutPlayerStateChangeListenerPlugin : NutPlugin, NutEventListener {
    override val playerEvents: Array<KClass<out NutEvent>> = arrayOf(OnPlayerStateChange::class)

    private var lastEvent = "unknown"
    private var map = emptyMap<String, Any>()
    var onMessageFetched: ((Map<String, Any>) -> Unit)? = null
    var onMessageFetchedError: ((NutPlayerState) -> Unit)? = null

    override fun onEvent(nutEvent: NutEvent) {
        if (nutEvent is OnPlayerStateChange) {
            endBufferisationIfNeeded(nutEvent.nutPlayerState)
            when (nutEvent.nutPlayerState) {
                is BufferingState -> {
                    if (lastEvent != "unknown") {
                        lastEvent = "bufferingStart"
                        map = mapOf<String, Any>(
                            "event" to lastEvent
                        )
                    }
                }

                is ErrorState -> {
                    onMessageFetchedError?.invoke(nutEvent.nutPlayerState)
                }

                is FinishState -> {
                    lastEvent = "completed"
                    map = mapOf<String, Any>(
                        "event" to lastEvent
                    )
                }

                is PauseState -> {
                    lastEvent = "isPlayingStateUpdate"
                    map = mapOf<String, Any>(
                        "event" to lastEvent,
                        "isPlaying" to false
                    )
                }

                is PlayState -> {
                    lastEvent = "isPlayingStateUpdate"
                    map = mapOf<String, Any>(
                        "event" to lastEvent,
                        "isPlaying" to true
                    )
                }

                is ReadyState -> {
                    lastEvent = "ready"
                    map = mapOf<String, Any>(
                        "event" to lastEvent,
                        "duration" to "lateDuration"
                    )
                }

                else -> println("STATE - ${nutEvent.nutPlayerState}")
            }
            onMessageFetched?.invoke(map)
        }
    }

    private fun endBufferisationIfNeeded(state: NutPlayerState) {
        if (lastEvent == "bufferingStart" && state !is BufferingState && state !is ContentLoadingState) {
            lastEvent = "bufferingEnd"
            map = mapOf<String, Any>("event" to lastEvent)
        }
    }
}