package dev.coffeeco.homenative.data import io.ktor.client.HttpClient import io.ktor.client.call.body import io.ktor.client.engine.okhttp.OkHttp import io.ktor.client.plugins.DefaultRequest import io.ktor.client.plugins.contentnegotiation.ContentNegotiation import io.ktor.client.plugins.websocket.DefaultClientWebSocketSession import io.ktor.client.plugins.websocket.WebSockets import io.ktor.client.plugins.websocket.receiveDeserialized import io.ktor.client.plugins.websocket.sendSerialized import io.ktor.client.plugins.websocket.webSocket import io.ktor.client.plugins.websocket.webSocketSession import io.ktor.client.request.get import io.ktor.client.request.header import io.ktor.client.request.post import io.ktor.client.request.setBody import io.ktor.client.statement.HttpResponse import io.ktor.http.ContentType import io.ktor.http.HttpHeaders import io.ktor.http.contentType import io.ktor.serialization.kotlinx.KotlinxWebsocketSerializationConverter import io.ktor.serialization.kotlinx.json.json import io.ktor.utils.io.InternalAPI import io.ktor.websocket.DefaultWebSocketSession import io.ktor.websocket.FrameType import io.ktor.websocket.send import io.ktor.websocket.serialization.receiveDeserializedBase import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.serialization.json.Json import java.util.EventListener class HomeClient(private val baseUrl: String, private val accessToken: String) { val jsonConfig = Json { // isLenient = true // useArrayPolymorphism = true allowStructuredMapKeys = true ignoreUnknownKeys = true // explicitNulls = false // namingStrategy = JsonNamingStrategy.SnakeCase encodeDefaults = true // IMPORTANT } private val client: HttpClient = HttpClient(OkHttp) { install(WebSockets) { contentConverter = KotlinxWebsocketSerializationConverter(Json) } install(ContentNegotiation) { json(jsonConfig) } install(DefaultRequest) { header(HttpHeaders.Authorization, "Bearer $accessToken") } } val wsClient = WSClient(GlobalScope, baseUrl, accessToken, client) suspend fun apiStatus(): HttpResponse { val res = client.get("$baseUrl/api/") return res } private suspend fun getState(): List { val res = client.get("$baseUrl/api/states") val body = res.body>() return body } suspend fun getUsefulState(): List { val all = getState() val filtered = all.filter { i -> i.entityId.startsWith("switch.") } return filtered } private suspend fun updateService( entityId: String, domain: String, service: String ): HttpResponse { return client.post("$baseUrl/api/services/$domain/$service") { contentType(ContentType.Application.Json) setBody(PostServiceBody(entityId)) } } suspend fun updateSwitch(entityId: String, service: String) { if (service !in switchServices) { throw Exception("Illegal/unknown service was specified") } val res = updateService(entityId, "switch", service) } } val switchServices = listOf("turn_off", "turn_on", "toggle")