package de.tsschulz.tt_tagebuch.shared.api.models

import kotlinx.serialization.KSerializer
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.JsonDecoder
import kotlinx.serialization.json.JsonEncoder
import kotlinx.serialization.json.JsonNull
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.contentOrNull

/**
 * The API may expose drawing data as stored JSON text or as an expanded JSON object.
 * The app keeps one canonical text representation for the existing drawing parser.
 */
object FlexibleNullableDrawingDataSerializer : KSerializer<String?> {
    override val descriptor: SerialDescriptor =
        PrimitiveSerialDescriptor("FlexibleNullableDrawingData", PrimitiveKind.STRING)

    override fun deserialize(decoder: Decoder): String? {
        val input = decoder as? JsonDecoder
            ?: error("FlexibleNullableDrawingDataSerializer requires JsonDecoder")
        return when (val element = input.decodeJsonElement()) {
            is JsonNull -> null
            is JsonPrimitive -> element.contentOrNull
            else -> element.toString()
        }
    }

    @OptIn(ExperimentalSerializationApi::class)
    override fun serialize(encoder: Encoder, value: String?) {
        when (encoder) {
            is JsonEncoder -> encoder.encodeJsonElement(
                if (value == null) JsonNull else JsonPrimitive(value),
            )
            else -> if (value == null) encoder.encodeNull() else encoder.encodeString(value)
        }
    }
}
