package com.iscs.bozzys.utils

import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.descriptors.SerialKind
import kotlinx.serialization.descriptors.StructureKind
import kotlinx.serialization.descriptors.buildSerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.encoding.encodeCollection
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonDecoder
import kotlinx.serialization.json.JsonNull
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.jsonPrimitive

/**
 * 解析多类型字段
 */
object StringToListSerializer : KSerializer<List<String>> {

    @OptIn(InternalSerializationApi::class, ExperimentalSerializationApi::class)
    override val descriptor: SerialDescriptor = buildSerialDescriptor("StringList", SerialKind.CONTEXTUAL)

    /**
     * 序列化为对象
     */
    override fun deserialize(decoder: Decoder): List<String> {
        val jsonDecoder = decoder as? JsonDecoder ?: error("This serializer can be used only with Json")

        return when (val element = jsonDecoder.decodeJsonElement()) {
            is JsonPrimitive -> {
                if (element.isString) {
                    listOf(element.content)
                } else {
                    emptyList()
                }
            }

            is JsonArray -> {
                element.mapNotNull {
                    it.jsonPrimitive.contentOrNull
                }
            }

            JsonNull -> emptyList()
            else -> emptyList()
        }
    }

    /**
     * 序列化为JSON
     */
    @OptIn(InternalSerializationApi::class, ExperimentalSerializationApi::class)
    override fun serialize(encoder: Encoder, value: List<String>) {
        if (value.size <= 1) {
            encoder.encodeString(value.getOrNull(0) ?: "")
        } else {
            val desc = buildSerialDescriptor("StringList", StructureKind.LIST)
            encoder.encodeCollection(desc, value.size) {
                value.forEachIndexed { index, item -> encodeStringElement(desc, index, item) }
            }
        }
    }
}
