/*
 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
 */

package kotlinx.coroutines.experimental.android

import android.os.Handler
import android.os.Looper
import android.view.Choreographer
import kotlinx.coroutines.experimental.*
import java.util.concurrent.TimeUnit
import kotlin.coroutines.experimental.CoroutineContext

/**
 * Dispatches execution onto Android main UI thread and provides native [delay][Delay.delay] support.
 */
val UI = HandlerContext(Handler(Looper.getMainLooper()), "UI")

/**
 * Represents an arbitrary [Handler] as a implementation of [CoroutineDispatcher].
 */
fun Handler.asCoroutineDispatcher() = HandlerContext(this)

private const val MAX_DELAY = Long.MAX_VALUE / 2 // cannot delay for too long on Android

/**
 * Implements [CoroutineDispatcher] on top of an arbitrary Android [Handler].
 * @param handler a handler.
 * @param name an optional name for debugging.
 */
public class HandlerContext(
    private val handler: Handler,
    private val name: String? = null
) : CoroutineDispatcher(), Delay {
    @Volatile
    private var _choreographer: Choreographer? = null

    override fun dispatch(context: CoroutineContext, block: Runnable) {
        handler.post(block)
    }

    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) {
        handler.postDelayed({
            with(continuation) { resumeUndispatched(Unit) }
        }, unit.toMillis(time).coerceAtMost(MAX_DELAY))
    }

    override fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle {
        handler.postDelayed(block, unit.toMillis(time).coerceAtMost(MAX_DELAY))
        return object : DisposableHandle {
            override fun dispose() {
                handler.removeCallbacks(block)
            }
        }
    }

    /**
     * Awaits the next animation frame and returns frame time in nanoseconds.
     */
    public suspend fun awaitFrame(): Long {
        // fast path when choreographer is already known
        val choreographer = _choreographer
        if (choreographer != null) {
            return suspendCancellableCoroutine { cont ->
                postFrameCallback(choreographer, cont)
            }
        }
        // post into looper thread thread to figure it out
        return suspendCancellableCoroutine { cont ->
           handler.post {
               updateChoreographerAndPostFrameCallback(cont)
           }
        }
    }

    private fun updateChoreographerAndPostFrameCallback(cont: CancellableContinuation<Long>) {
        val choreographer = _choreographer ?:
            Choreographer.getInstance()!!.also { _choreographer = it }
        postFrameCallback(choreographer, cont)
    }

    private fun postFrameCallback(choreographer: Choreographer, cont: CancellableContinuation<Long>) {
        choreographer.postFrameCallback { nanos ->
            with(cont) { resumeUndispatched(nanos) }
        }
    }

    override fun toString() = name ?: handler.toString()
    override fun equals(other: Any?): Boolean = other is HandlerContext && other.handler === handler
    override fun hashCode(): Int = System.identityHashCode(handler)
}
