package ru.dbotthepony.kstarbound.util

import com.google.gson.JsonElement
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.json.builder.IStringSerializable
import java.util.*
import java.util.stream.Stream
import kotlin.NoSuchElementException
import kotlin.collections.Collection

fun String.sbIntern(): String {
	return Starbound.STRINGS.intern(this)
}

fun String.sbIntern2(): String {
	return Starbound.STRINGS.intern(this.intern())
}

val JsonElement.asStringOrNull: String?
	get() = if (isJsonNull) null else asString

val JsonElement.coalesceNull: JsonElement?
	get() = if (isJsonNull) null else this

fun UUID.toStarboundString(): String {
	val builder = StringBuilder(32)
	val a = java.lang.Long.toUnsignedString(mostSignificantBits, 16)
	val b = java.lang.Long.toUnsignedString(leastSignificantBits, 16)

	for (i in a.length until 16)
		builder.append("0")

	builder.append(a)

	for (i in b.length until 16)
		builder.append("0")

	builder.append(b)

	return builder.toString()
}

fun uuidFromStarboundString(value: String): UUID {
	if (value.length != 32) {
		throw IllegalArgumentException("Not a UUID string: $value")
	}

	val a = value.substring(0, 16)
	val b = value.substring(16)

	return UUID(a.toLong(16), b.toLong(16))
}

fun paddedNumber(number: Int, digits: Int): String {
	val str = number.toString()

	if (str.length > digits) {
		return str.substring(0, digits)
	} else if (str.length == digits) {
		return str
	} else {
		return "0".repeat(digits - str.length) + str
	}
}

fun <C : Comparable<C>, T : Any> Stream<Pair<C, T>>.binnedChoice(value: C): Optional<T> {
	return this.sorted { o1, o2 -> o2.first.compareTo(o1.first) }
		.filter { it.first <= value }
		.findFirst().map { it.second }
}

fun <E : IStringSerializable> Collection<E>.valueOf(value: String): E {
	return firstOrNull { it.match(value) } ?: throw NoSuchElementException("$value is not a valid element")
}
