package app.furmeet.events.system.helper

import android.app.Activity
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import java.io.PrintWriter
import java.io.StringWriter

fun logException(clazz: Class<*>, throwable: Throwable) =
        Log.e(clazz.name, StringWriter().apply { throwable.printStackTrace(PrintWriter(this)) }.toString())

fun Any.logException(throwable: Throwable) = logException(this::class.java, throwable)


fun <K> logIfException(clazz: Class<*>, runnable: () -> K, finallyTerm: () -> Unit = nullFun): K? =
        try {
            run(runnable)
        } catch (throwable: Throwable) {
            logException(clazz, throwable)
            null
        } finally {
            finallyTerm()
        }

fun <K> logIfException(obj: Any, runnable: () -> K, finallyTerm: () -> Unit = nullFun): K? = logIfException(obj::class.java, runnable, finallyTerm)

fun <K> Any.nullAndLogIfException(runnable: () -> K): K? = logIfException(this, runnable)

fun <K> AppCompatActivity.uiThreadWithLogger(runnable: () -> K): Unit =
        uiThread { logIfException(this, runnable) }

fun <K> Any.doAsyncWithLogger(runnable: () -> K) =
        doAsync { logIfException(this, runnable) }

fun <K> Any.doAsyncWithLoggerAndFinally(runnable: () -> K, finallyTerm: () -> Unit) =
        doAsync { logIfException(this, runnable, finallyTerm) }

fun <K> Activity.runOnUiThreadWithLogger(runnable: () -> K): Unit =
        this.runOnUiThread { logIfException(this, runnable) }

fun <T> Iterable<T>.forEachWithLogger(runnable: (T) -> Unit) {
    forEach { nullAndLogIfException { runnable(it) } }
}