package com.gametime.watch.bridge

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

class WatchBridgeListenerService : WearableListenerService() {
    override fun onDataChanged(dataEvents: DataEventBuffer) {
        WatchBridgePlugin.attachApplicationContext(applicationContext)
        try {
            for (event in dataEvents) {
                WatchBridgePlugin.handleDataEvent(event)
            }
        } finally {
            dataEvents.release()
        }
    }

    override fun onMessageReceived(messageEvent: MessageEvent) {
        WatchBridgePlugin.attachApplicationContext(applicationContext)
        val payload = JSONObject(String(messageEvent.data, StandardCharsets.UTF_8))
        when (messageEvent.path) {
            WatchBridgePlugin.ACK_PATH -> WatchBridgePlugin.emitAck(payload.toMap())
            WatchBridgePlugin.ALERT_PATH -> WatchBridgePlugin.handleAlert(payload.toMap())
        }
    }

    override fun onCapabilityChanged(capabilityInfo: CapabilityInfo) {
        WatchBridgePlugin.attachApplicationContext(applicationContext)
        if (capabilityInfo.name != WatchBridgePlugin.PHONE_CAPABILITY) {
            return
        }
        WatchBridgePlugin.emitConnection(
            isReachable = capabilityInfo.nodes.isNotEmpty(),
            requestsResync = capabilityInfo.nodes.isNotEmpty(),
        )
        if (capabilityInfo.nodes.isNotEmpty()) {
            WatchBridgePlugin.resyncLiveStatsAfterReconnect(applicationContext)
            WatchBridgePlugin.requestLatestProjection(applicationContext)
        }
    }

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

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
}
