package tech.nut.nut_player_android

import tech.nut.player.model.ContentLoaded
import tech.nut.player.model.ContentLoading
import tech.nut.player.model.Error
import tech.nut.player.model.HttpError
import tech.nut.player.model.LoadError
import tech.nut.player.model.ManifestLoaded
import tech.nut.player.model.ManifestLoading
import tech.nut.player.model.NutEvent
import tech.nut.player.model.OnPlayerStateChange
import tech.nut.player.model.Seeked
import tech.nut.player.model.VolumeChanged
import tech.nut.player.model.plugin.NutEventListener
import tech.nut.player.model.plugin.NutPlugin
import java.text.SimpleDateFormat
import java.util.Locale
import kotlin.reflect.KClass

class NutPlayerLoggerPlugin : NutPlugin, NutEventListener {

    var onMessageFetched: ((String) -> Unit)? = null
    private val dateFormat by lazy { SimpleDateFormat("hh:mm:ss:SSS", Locale.US) }

    override val playerEvents: Array<KClass<out NutEvent>> = arrayOf(
        Error::class,
        Seeked::class,
        LoadError::class,
        ContentLoaded::class,
        VolumeChanged::class,
        ContentLoading::class,
        ManifestLoaded::class,
        ManifestLoading::class,
        OnPlayerStateChange::class
    )

    override fun onEvent(nutEvent: NutEvent) {
        val date = dateFormat.format(System.currentTimeMillis())
        val message = "$date | " + map(nutEvent)
        onMessageFetched?.invoke(message)
    }

    private fun map(event: NutEvent): String =
        when (event) {
            ManifestLoaded -> "Манифест загружен"
            is Error -> getMessageError(event)
            is ManifestLoading -> "Старт загрузки манифеста: ${event.url}"
            is ContentLoading -> "Получение контента от провайдера"
            is ContentLoaded -> "Успешное получение контента: ${event.content}"
            is OnPlayerStateChange -> "Состояние: ${event.nutPlayerState.javaClass.simpleName}"
            else -> event.toString()
        }

    private fun getMessageError(event: Error): String {
        val mainErrorMessage = "Ошибка. Компонент: ${event.component}, тип: ${event.type}"
        var resultMessage = mainErrorMessage
        (event.cause as? HttpError)?.let { error ->
            val additionInfo = ", Код: ${error.code}, описание: ${error.description}"
            resultMessage += " $additionInfo"
        }
        (event as? LoadError)?.url?.let { url ->
            resultMessage += ", Url: $url"
        }
        event.cause?.let {
            resultMessage += ", описание: ${it.cause}, название ошибки: ${it.message}"
        }
        return resultMessage
    }
}