/*
 * Copyright 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.wear.watchface.client

import android.graphics.Bitmap
import android.os.Handler
import android.os.HandlerThread
import android.os.RemoteException
import android.support.wearable.watchface.SharedMemoryImage
import androidx.annotation.AnyThread
import androidx.annotation.Px
import androidx.annotation.RequiresApi
import androidx.wear.watchface.complications.data.ComplicationData
import androidx.wear.watchface.complications.data.toApiComplicationText
import androidx.wear.watchface.utility.TraceEvent
import androidx.wear.watchface.ComplicationSlot
import androidx.wear.watchface.ComplicationSlotsManager
import androidx.wear.watchface.ContentDescriptionLabel
import androidx.wear.watchface.RenderParameters
import androidx.wear.watchface.TapType
import androidx.wear.watchface.control.IInteractiveWatchFace
import androidx.wear.watchface.control.data.WatchFaceRenderParams
import androidx.wear.watchface.ComplicationSlotBoundsType
import androidx.wear.watchface.control.IWatchfaceReadyListener
import androidx.wear.watchface.data.IdAndComplicationDataWireFormat
import androidx.wear.watchface.data.WatchUiState
import androidx.wear.watchface.style.UserStyle
import androidx.wear.watchface.style.UserStyleSchema
import androidx.wear.watchface.style.UserStyleSetting.ComplicationSlotsUserStyleSetting
import androidx.wear.watchface.style.UserStyleData
import java.time.Instant
import java.util.concurrent.Executor

/**
 * Controls a stateful remote interactive watch face. Typically this will be used for the current
 * active watch face.
 *
 * Note clients should call [close] when finished.
 */
public interface InteractiveWatchFaceClient : AutoCloseable {
    /**
     * Sends new [ComplicationData] to the watch face. Note this doesn't have to be a full update,
     * it's possible to update just one complication at a time, but doing so may result in a less
     * visually clean transition.
     *
     * @param slotIdToComplicationData The [ComplicationData] for each
     * [androidx.wear.watchface.ComplicationSlot].
     */
    @Throws(RemoteException::class)
    public fun updateComplicationData(slotIdToComplicationData: Map<Int, ComplicationData>)

    /**
     * Renders the watchface to a shared memory backed [Bitmap] with the given settings.
     *
     * @param renderParameters The [RenderParameters] to draw with.
     * @param instant The [Instant] render with.
     * @param userStyle Optional [UserStyle] to render with, if null the current style is used.
     * @param idAndComplicationData Map of complication ids to [ComplicationData] to render with, or
     * if null then the existing complication data if any is used.
     * @return A shared memory backed [Bitmap] containing a screenshot of the watch  face with the
     * given settings.
     */
    @RequiresApi(27)
    @Throws(RemoteException::class)
    public fun renderWatchFaceToBitmap(
        renderParameters: RenderParameters,
        instant: Instant,
        userStyle: UserStyle?,
        idAndComplicationData: Map<Int, ComplicationData>?
    ): Bitmap

    /** The UTC reference preview time for this watch face in milliseconds since the epoch. */
    @get:Throws(RemoteException::class)
    public val previewReferenceInstant: Instant

    /**
     * Renames this instance to [newInstanceId] (must be unique, usually this would be different
     * from the old ID but that's not a requirement). Sets the current [UserStyle] and clears
     * any complication data. Setting the new UserStyle may have a side effect of enabling or
     * disabling complicationSlots, which will be visible via [ComplicationSlotState.isEnabled].
     *
     * NB [setWatchUiState] and [updateWatchFaceInstance] can be called in any order.
     */
    @Throws(RemoteException::class)
    public fun updateWatchFaceInstance(newInstanceId: String, userStyle: UserStyle)

    /**
     * Renames this instance to [newInstanceId] (must be unique, usually this would be different
     * from the old ID but that's not a requirement). Sets the current [UserStyle] represented as a
     * [UserStyleData> and clears any complication data. Setting the new UserStyle may have a
     * side effect of enabling or disabling complicationSlots, which will be visible via
     * [ComplicationSlotState.isEnabled].
     */
    @Throws(RemoteException::class)
    public fun updateWatchFaceInstance(newInstanceId: String, userStyle: UserStyleData)

    /** Returns the ID of this watch face instance. */
    @get:Throws(RemoteException::class)
    public val instanceId: String

    /** The watch face's [UserStyleSchema]. */
    @get:Throws(RemoteException::class)
    public val userStyleSchema: UserStyleSchema

    /**
     * Map of [androidx.wear.watchface.ComplicationSlot] ids to [ComplicationSlotState] for each
     * [ComplicationSlot] registered with the  watch face's [ComplicationSlotsManager]. The
     * ComplicationSlotState is based on the initial state of each
     * [androidx.wear.watchface.ComplicationSlot] plus any overrides from a
     * [ComplicationSlotsUserStyleSetting]. As a consequence ComplicationSlotState may update based
     * on style changes.
     */
    @get:Throws(RemoteException::class)
    public val complicationSlotsState: Map<Int, ComplicationSlotState>

    /**
     * Returns the ID of the [androidx.wear.watchface.ComplicationSlot] at the given coordinates or
     * `null` if there isn't one.
     *
     * Note this currently doesn't support Edge complications.
     */
    @SuppressWarnings("AutoBoxing")
    @Throws(RemoteException::class)
    public fun getComplicationIdAt(@Px x: Int, @Px y: Int): Int? =
        complicationSlotsState.asSequence().firstOrNull {
            it.value.isEnabled && when (it.value.boundsType) {
                ComplicationSlotBoundsType.ROUND_RECT -> it.value.bounds.contains(x, y)
                ComplicationSlotBoundsType.BACKGROUND -> false
                ComplicationSlotBoundsType.EDGE -> false
                else -> false
            }
        }?.key

    public companion object {
        /** Indicates a "down" touch event on the watch face. */
        public const val TAP_TYPE_DOWN: Int = IInteractiveWatchFace.TAP_TYPE_DOWN

        /**
         * Indicates that a previous [TAP_TYPE_DOWN] event has been canceled. This generally happens
         * when the watch face is touched but then a move or long press occurs.
         */
        public const val TAP_TYPE_CANCEL: Int = IInteractiveWatchFace.TAP_TYPE_CANCEL

        /**
         * Indicates that an "up" event on the watch face has occurred that has not been consumed by
         * another activity. A [TAP_TYPE_DOWN] always occur first. This event will not occur if a
         * [TAP_TYPE_CANCEL] is sent.
         */
        public const val TAP_TYPE_UP: Int = IInteractiveWatchFace.TAP_TYPE_UP
    }

    /**
     * Sends a tap event to the watch face for processing.
     */
    @Throws(RemoteException::class)
    public fun sendTouchEvent(@Px xPosition: Int, @Px yPosition: Int, @TapType tapType: Int)

    /**
     * Returns the [ContentDescriptionLabel]s describing the watch face, for the use by screen
     * readers.
     */
    @get:Throws(RemoteException::class)
    public val contentDescriptionLabels: List<ContentDescriptionLabel>

    /**
     * Updates the watch faces [WatchUiState]. NB [setWatchUiState] and [updateWatchFaceInstance]
     * can be called in any order.
     */
    @Throws(RemoteException::class)
    public fun setWatchUiState(watchUiState: androidx.wear.watchface.client.WatchUiState)

    /** Triggers watch face rendering into the surface when in ambient mode. */
    @Throws(RemoteException::class)
    public fun performAmbientTick()

    /**
     * Callback that observes when the client disconnects. Use [addClientDisconnectListener] to
     * register a ClientDisconnectListener.
     */
    public interface ClientDisconnectListener {
        /**
         * The client disconnected, typically due to the server side crashing. Note this is not
         * called in response to [close] being called on [InteractiveWatchFaceClient].
         */
        public fun onClientDisconnected()
    }

    /** Registers a [ClientDisconnectListener]. */
    @AnyThread
    public fun addClientDisconnectListener(listener: ClientDisconnectListener, executor: Executor)

    /**
     * Removes a [ClientDisconnectListener] previously registered by [addClientDisconnectListener].
     */
    @AnyThread
    public fun removeClientDisconnectListener(listener: ClientDisconnectListener)

    /** Returns true if the connection to the server side is alive. */
    @AnyThread
    public fun isConnectionAlive(): Boolean

    /**
     * Interface passed to [addOnWatchFaceReadyListener] which calls
     * [OnWatchFaceReadyListener.onWatchFaceReady] when the watch face is ready to render. Use
     * [addOnWatchFaceReadyListener] to register a OnWatchFaceReadyListener.
     */
    public fun interface OnWatchFaceReadyListener {
        /**
         * Called when the watchface is ready to render.
         *
         * Note in the event of the watch face disconnecting (e.g. due to a crash) this callback
         * will never fire. Use [ClientDisconnectListener] to observe disconnects.
         */
        public fun onWatchFaceReady()
    }

    /**
     * Registers a [OnWatchFaceReadyListener] which gets called when the watch face is ready to
     * render.
     *
     * Note in the event of the watch face disconnecting (e.g. due to a crash) the listener will
     * never get called. Use [ClientDisconnectListener] to observe disconnects.
     *
     * @param executor The [Executor] on which to run [OnWatchFaceReadyListener].
     * @param listener The [OnWatchFaceReadyListener] to run when the watchface is ready to render.
     */
    public fun addOnWatchFaceReadyListener(executor: Executor, listener: OnWatchFaceReadyListener)

    /**
     * Stops listening for events registered by [addOnWatchFaceReadyListener].
     */
    public fun removeOnWatchFaceReadyListener(listener: OnWatchFaceReadyListener)
}

/** Controls a stateful remote interactive watch face. */
internal class InteractiveWatchFaceClientImpl internal constructor(
    private val iInteractiveWatchFace: IInteractiveWatchFace
) : InteractiveWatchFaceClient {

    private val lock = Any()
    private val disconnectListeners =
        HashMap<InteractiveWatchFaceClient.ClientDisconnectListener, Executor>()
    private val readyListeners =
        HashMap<InteractiveWatchFaceClient.OnWatchFaceReadyListener, Executor>()
    private var watchfaceReadyListenerRegistered = false
    private var closed = false

    init {
        iInteractiveWatchFace.asBinder().linkToDeath(
            {
                var listenerCopy:
                    HashMap<InteractiveWatchFaceClient.ClientDisconnectListener, Executor>

                synchronized(lock) {
                    listenerCopy = HashMap(disconnectListeners)
                }

                for ((listener, executor) in listenerCopy) {
                    executor.execute {
                        listener.onClientDisconnected()
                    }
                }
            },
            0
        )
    }

    override fun updateComplicationData(
        slotIdToComplicationData: Map<Int, ComplicationData>
    ) = TraceEvent("InteractiveWatchFaceClientImpl.updateComplicationData").use {
        iInteractiveWatchFace.updateComplicationData(
            slotIdToComplicationData.map {
                IdAndComplicationDataWireFormat(it.key, it.value.asWireComplicationData())
            }
        )
    }

    @RequiresApi(27)
    override fun renderWatchFaceToBitmap(
        renderParameters: RenderParameters,
        instant: Instant,
        userStyle: UserStyle?,
        idAndComplicationData: Map<Int, ComplicationData>?
    ): Bitmap = TraceEvent("InteractiveWatchFaceClientImpl.renderWatchFaceToBitmap").use {
        SharedMemoryImage.ashmemReadImageBundle(
            iInteractiveWatchFace.renderWatchFaceToBitmap(
                WatchFaceRenderParams(
                    renderParameters.toWireFormat(),
                    instant.toEpochMilli(),
                    userStyle?.toWireFormat(),
                    idAndComplicationData?.map {
                        IdAndComplicationDataWireFormat(
                            it.key,
                            it.value.asWireComplicationData()
                        )
                    }
                )
            )
        )
    }

    override val previewReferenceInstant: Instant
        get() = Instant.ofEpochMilli(iInteractiveWatchFace.previewReferenceTimeMillis)

    override fun updateWatchFaceInstance(newInstanceId: String, userStyle: UserStyle) = TraceEvent(
        "InteractiveWatchFaceClientImpl.updateInstance"
    ).use {
        iInteractiveWatchFace.updateWatchfaceInstance(newInstanceId, userStyle.toWireFormat())
    }

    override fun updateWatchFaceInstance(
        newInstanceId: String,
        userStyle: UserStyleData
    ) = TraceEvent(
        "InteractiveWatchFaceClientImpl.updateInstance"
    ).use {
        iInteractiveWatchFace.updateWatchfaceInstance(
            newInstanceId,
            userStyle.toWireFormat()
        )
    }

    override val instanceId: String
        get() = iInteractiveWatchFace.instanceId

    override val userStyleSchema: UserStyleSchema
        get() = UserStyleSchema(iInteractiveWatchFace.userStyleSchema)

    override val complicationSlotsState: Map<Int, ComplicationSlotState>
        get() = iInteractiveWatchFace.complicationDetails.associateBy(
            { it.id },
            { ComplicationSlotState(it.complicationState) }
        )

    override fun close() = TraceEvent("InteractiveWatchFaceClientImpl.close").use {
        iInteractiveWatchFace.release()
        synchronized(lock) {
            closed = true
        }
    }

    override fun sendTouchEvent(
        xPosition: Int,
        yPosition: Int,
        @TapType tapType: Int
    ) = TraceEvent("InteractiveWatchFaceClientImpl.sendTouchEvent").use {
        iInteractiveWatchFace.sendTouchEvent(xPosition, yPosition, tapType)
    }

    override val contentDescriptionLabels: List<ContentDescriptionLabel>
        get() = iInteractiveWatchFace.contentDescriptionLabels.map {
            ContentDescriptionLabel(
                it.text.toApiComplicationText(),
                it.bounds,
                it.tapAction
            )
        }

    override fun setWatchUiState(
        watchUiState: androidx.wear.watchface.client.WatchUiState
    ) = TraceEvent(
        "InteractiveWatchFaceClientImpl.setSystemState"
    ).use {
        iInteractiveWatchFace.setWatchUiState(
            WatchUiState(
                watchUiState.inAmbientMode,
                watchUiState.interruptionFilter
            )
        )
    }

    override fun performAmbientTick() = TraceEvent(
        "InteractiveWatchFaceClientImpl.performAmbientTick"
    ).use {
        iInteractiveWatchFace.ambientTickUpdate()
    }

    override fun addClientDisconnectListener(
        listener: InteractiveWatchFaceClient.ClientDisconnectListener,
        executor: Executor
    ) {
        synchronized(lock) {
            require(!disconnectListeners.contains(listener)) {
                "Don't call addClientDisconnectListener multiple times for the same listener"
            }
            disconnectListeners.put(listener, executor)
        }
    }

    override fun removeClientDisconnectListener(
        listener: InteractiveWatchFaceClient.ClientDisconnectListener
    ) {
        synchronized(lock) {
            disconnectListeners.remove(listener)
        }
    }

    override fun isConnectionAlive() =
        iInteractiveWatchFace.asBinder().isBinderAlive && synchronized(lock) { !closed }

    private fun registerWatchfaceReadyListener() {
        if (watchfaceReadyListenerRegistered) {
            return
        }
        if (iInteractiveWatchFace.apiVersion >= 2) {
            iInteractiveWatchFace.addWatchfaceReadyListener(
                object : IWatchfaceReadyListener.Stub() {
                    override fun getApiVersion(): Int = IWatchfaceReadyListener.API_VERSION

                    override fun onWatchfaceReady() {
                        this@InteractiveWatchFaceClientImpl.onWatchFaceReady()
                    }
                }
            )
        } else {
            // We can emulate this on an earlier API by using a call to get userStyleSchema that
            // will block until the watch face is ready. to Avoid blocking the current thread we
            // spin up a temporary thread.
            val thread = HandlerThread("addWatchFaceReadyListener")
            thread.start()
            val handler = Handler(thread.looper)
            handler.post {
                iInteractiveWatchFace.userStyleSchema
                this@InteractiveWatchFaceClientImpl.onWatchFaceReady()
                thread.quitSafely()
            }
        }
        watchfaceReadyListenerRegistered = true
    }

    internal fun onWatchFaceReady() {
        var listenerCopy: HashMap<InteractiveWatchFaceClient.OnWatchFaceReadyListener, Executor>

        synchronized(lock) {
            listenerCopy = HashMap(readyListeners)
        }

        for ((listener, executor) in listenerCopy) {
            executor.execute {
                listener.onWatchFaceReady()
            }
        }
    }

    override fun addOnWatchFaceReadyListener(
        executor: Executor,
        listener: InteractiveWatchFaceClient.OnWatchFaceReadyListener
    ) {
        synchronized(lock) {
            require(!readyListeners.contains(listener)) {
                "Don't call addWatchFaceReadyListener multiple times for the same listener"
            }
            registerWatchfaceReadyListener()
            readyListeners.put(listener, executor)
        }
    }

    override fun removeOnWatchFaceReadyListener(
        listener: InteractiveWatchFaceClient.OnWatchFaceReadyListener
    ) {
        synchronized(lock) {
            readyListeners.remove(listener)
        }
    }
}
