package launchers

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import java.net.URI
import kotlin.text.Charsets.UTF_8

private const val VERSIONS_RESOURCE = "/upstream-versions.json"
private val VERSION_PATTERN = Regex("[A-Za-z0-9._+-]+")
private val SHA256_PATTERN = Regex("[0-9a-f]{64}")
private val JSON = Json { ignoreUnknownKeys = true }

@Serializable
internal data class LockedArtifact(
    val version: String,
    val url: String,
    val sha256: String,
) {
    init {
        require(VERSION_PATTERN.matches(version)) { "Invalid locked artifact version" }
        require(URI.create(url).let { it.scheme == "https" && it.host != null && it.userInfo == null }) {
            "Locked artifact URL must be an HTTPS URL without user information"
        }
        require(SHA256_PATTERN.matches(sha256)) { "Invalid locked artifact SHA-256" }
    }
}

@Serializable
internal data class UpstreamVersions(
    val bedrock: LockedArtifact,
    val minecraft: LockedArtifact,
    val fabric: LockedArtifact,
    val geyser: LockedArtifact,
    @SerialName("mcxboxbroadcast")
    val mcXboxBroadcast: LockedArtifact,
)

internal object Versions {
    private val upstreamVersions: UpstreamVersions by lazy {
        val contents =
            UpstreamVersions::class.java.getResourceAsStream(VERSIONS_RESOURCE)?.use { input ->
                input.readBytes().toString(UTF_8)
            } ?: error("Missing $VERSIONS_RESOURCE")
        JSON.decodeFromString<UpstreamVersions>(contents)
    }

    val minecraft: LockedArtifact
        get() = upstreamVersions.minecraft

    val fabric: LockedArtifact
        get() = upstreamVersions.fabric

    val geyser: LockedArtifact
        get() = upstreamVersions.geyser

    val mcXboxBroadcast: LockedArtifact
        get() = upstreamVersions.mcXboxBroadcast
}
