package app.furmeet.events.brasilfurfest.helper

import android.app.Activity
import android.util.Log
import org.jetbrains.anko.AnkoAsyncContext
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread
import java.io.PrintWriter
import java.io.StringWriter
import java.util.concurrent.Future

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> AnkoAsyncContext<*>.uiThreadWithLogger(runnable: () -> K): Boolean =
        uiThread { logIfException(this.weakRef.get()!!, runnable) }

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

fun <K> Any.doAsyncWithLoggerAndFinally(runnable: () -> K, finallyTerm: () -> Unit): Future<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) } }
}