package ru.dbotthepony.mc.otm.data

import com.google.gson.JsonArray
import com.google.gson.JsonNull
import com.google.gson.JsonObject
import com.mojang.serialization.DataResult
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet
import net.minecraft.world.entity.player.Player
import net.minecraft.world.level.storage.loot.LootContext
import net.minecraft.world.level.storage.loot.parameters.LootContextParam
import net.minecraft.world.level.storage.loot.parameters.LootContextParams

fun JsonArray.getRidOfNulls(): JsonArray {
	val toRemove = IntAVLTreeSet()

	for (i in 0 until size()) {
		when (val value = this[i]) {
			JsonNull.INSTANCE -> toRemove.add(i)
			is JsonArray -> value.getRidOfNulls()
			is JsonObject -> value.getRidOfNulls()
		}
	}

	if (toRemove.isNotEmpty()) {
		remove(toRemove.lastInt())
		val iterator = toRemove.iterator(toRemove.lastInt())

		while (iterator.hasPrevious()) {
			remove(iterator.previousInt())
		}
	}

	return this
}

fun JsonObject.getRidOfNulls(): JsonObject {
	val toRemove = ArrayList<String>()

	for ((key, value) in entrySet()) {
		when (value) {
			JsonNull.INSTANCE -> toRemove.add(key)
			is JsonArray -> value.getRidOfNulls()
			is JsonObject -> value.getRidOfNulls()
		}
	}

	for (key in toRemove) {
		remove(key)
	}

	return this
}

operator fun <T> LootContext.get(param: LootContextParam<T>): T? {
	return getParamOrNull(param)
}

fun <T> DataResult<T>.getOrNull(): T? {
	return get().left().orElse(null)
}

fun LootContext.findPlayer(): Player? {
	return getParamOrNull(LootContextParams.DIRECT_KILLER_ENTITY).let {
		if (it != null)
			it as? Player
		else
			getParamOrNull(LootContextParams.KILLER_ENTITY).let {
				if (it != null) it as? Player else getParamOrNull(LootContextParams.THIS_ENTITY) as? Player
			}
	}
}
