package com.complycube.reactnative.config.parser import com.complycube.sdk.presentation.theme.DesignTokens import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonNull import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive import kotlinx.serialization.json.buildJsonArray import kotlinx.serialization.json.buildJsonObject class DesignTokensParser( private val json: Json = Json { ignoreUnknownKeys = true isLenient = true } ) { fun parse(data: Map): DesignTokens { val normalized = data.toJsonObject() val payload = json.encodeToString(JsonObject.serializer(), normalized) return json.decodeFromString(DesignTokens.serializer(), payload) } private fun Map.toJsonObject(): JsonObject = buildJsonObject { for ((key, value) in this@toJsonObject) { put(key, value.toJsonElement()) } } private fun Any?.toJsonElement(): JsonElement = when (this) { null -> JsonNull is JsonElement -> this is String -> JsonPrimitive(this) is Boolean -> JsonPrimitive(this) is Byte -> JsonPrimitive(toInt()) is Short -> JsonPrimitive(toInt()) is Int -> JsonPrimitive(this) is Long -> JsonPrimitive(this) is Float -> normalizeNumber(toDouble()) is Double -> normalizeNumber(this) is Number -> normalizeNumber(toDouble()) is Map<*, *> -> buildJsonObject { for ((key, value) in this@toJsonElement) { if (key is String) { put(key, value.toJsonElement()) } } } is Iterable<*> -> toJsonArray() is Array<*> -> toList().toJsonArray() else -> throw IllegalArgumentException( "Unsupported designTokens value type: ${this::class.java.simpleName}" ) } private fun Iterable<*>.toJsonArray(): JsonArray = buildJsonArray { for (value in this@toJsonArray) { add(value.toJsonElement()) } } private fun normalizeNumber(value: Double): JsonPrimitive { require(value.isFinite()) { "Unsupported non-finite number in designTokens" } val wholeValue = value.toLong() return if (value == wholeValue.toDouble()) { JsonPrimitive(wholeValue) } else { JsonPrimitive(value) } } }