package com.gametime.app.watch

import com.google.android.gms.wearable.CapabilityInfo
import com.google.android.gms.wearable.MessageEvent
import com.google.android.gms.wearable.Wearable
import com.google.android.gms.wearable.WearableListenerService
import org.json.JSONObject
import java.nio.charset.StandardCharsets

class PhoneWatchBridgeListenerService : WearableListenerService() {
    override fun onMessageReceived(messageEvent: MessageEvent) {
        val payload = JSONObject(String(messageEvent.data, StandardCharsets.UTF_8))
        when (messageEvent.path) {
            WatchBridgePlugin.COMMAND_PATH -> {
                val command = payload.toMap()
                val delivered = WatchBridgePlugin.emitCommand(command, messageEvent.sourceNodeId)
                if (!delivered) {
                    sendPhoneBusyAck(command, messageEvent.sourceNodeId)
                }
            }
            WatchBridgePlugin.SENSOR_SUMMARY_PATH -> {
                WatchBridgePlugin.emitSensorSummary(payload.toMap())
            }
            WatchBridgePlugin.SENSOR_SAMPLE_PATH -> {
                WatchBridgePlugin.emitSensorSample(payload.toMap())
            }
        }
    }

    override fun onCapabilityChanged(capabilityInfo: CapabilityInfo) {
        if (capabilityInfo.name != WatchBridgePlugin.WATCH_CAPABILITY) {
            return
        }
        WatchBridgePlugin.emitConnection(
            isReachable = capabilityInfo.nodes.isNotEmpty(),
            requestsResync = capabilityInfo.nodes.isNotEmpty(),
        )
    }

    override fun onCreate() {
        super.onCreate()
        WatchBridgePlugin.requestCapabilityRefresh(applicationContext)
    }

    private fun sendPhoneBusyAck(command: Map<String, Any?>, sourceNodeId: String) {
        val ack = JSONObject(
            mapOf(
                "schemaVersion" to (command["schemaVersion"] ?: 1),
                "commandId" to command["commandId"],
                "sessionId" to command["sessionId"],
                "expectedRevision" to command["expectedRevision"],
                "status" to "rejectedPhoneBusy",
                "ackedAtEpochMs" to System.currentTimeMillis(),
            ),
        ).toString().toByteArray(StandardCharsets.UTF_8)
        Wearable.getMessageClient(this)
            .sendMessage(sourceNodeId, WatchBridgePlugin.ACK_PATH, ack)
    }
}

private fun JSONObject.toMap(): Map<String, Any?> {
    val output = linkedMapOf<String, Any?>()
    val keys = keys()
    while (keys.hasNext()) {
        val key = keys.next()
        val value = get(key)
        output[key] = if (value == JSONObject.NULL) null else value
    }
    return output
}
