package net.taehui.twilight

import com.fasterxml.jackson.core.JsonProcessingException
import com.fasterxml.jackson.databind.ObjectMapper
import org.slf4j.LoggerFactory
import java.util.concurrent.CompletableFuture

interface Logger {
    fun logInfo(toNotify: String) {
        LoggerFactory.getLogger(javaClass).info(toNotify)
    }

    fun logFault(e: Throwable) {
        LoggerFactory.getLogger(javaClass).error(Utility.getFaultText(e))
    }

    fun <T> logValueFuture(onHandle: () -> T): CompletableFuture<T> {
        return CompletableFuture.supplyAsync {
            try {
                onHandle()
            } catch (e: Throwable) {
                logFault(e)
                throw e
            }
        }
    }

    fun logFuture(onHandle: () -> Unit): CompletableFuture<Void> {
        return CompletableFuture.runAsync {
            try {
                onHandle()
            } catch (e: Throwable) {
                logFault(e)
                throw e
            }
        }
    }

    fun logEvent(event: EventOuterClass.Event) {
        fun logEventImpl(event: EventOuterClass.Event) {
            logInfo((if (event.dataList.isEmpty()) event else EventOuterClass.Event.newBuilder().apply {
                eventID = event.eventID
                text = event.text
            }.build()).toString())
        }

        when (event.eventID) {
            EventOuterClass.Event.EventID.SIGN_IN -> {
                try {
                    val jm = ObjectMapper()
                    val text = jm.writeValueAsString(object {
                        val avatarID = jm.readValue(event.text, JSON.QwilightSignIn::class.java).avatarID
                        val avatarCipher = "*"
                    })
                    logEventImpl(EventOuterClass.Event.newBuilder().apply {
                        eventID = event.eventID
                        this.text = text
                    }.build())
                } catch (e: JsonProcessingException) {
                    logEventImpl(event)
                }
            }

            EventOuterClass.Event.EventID.SAVING_BUNDLE -> Unit
            EventOuterClass.Event.EventID.SAVING_AS_BUNDLE -> Unit
            EventOuterClass.Event.EventID.IO_INPUT -> Unit
            EventOuterClass.Event.EventID.IO_JUDGE -> Unit
            EventOuterClass.Event.EventID.IO_NOTE_VISIBILITY -> Unit
            EventOuterClass.Event.EventID.IO_JUDGMENT_METER -> Unit
            EventOuterClass.Event.EventID.IO_MULTIPLIER -> Unit
            EventOuterClass.Event.EventID.IO_AUDIO_MULTIPLIER -> Unit
            EventOuterClass.Event.EventID.IO_PAUSE -> Unit
            EventOuterClass.Event.EventID.AUDIO_INPUT -> Unit
            EventOuterClass.Event.EventID.CALL_NET -> Unit

            else -> {
                logEventImpl(event)
            }
        }
    }
}