package ru.dbotthepony.mc.otm.core.util

import it.unimi.dsi.fastutil.objects.Reference2IntFunction
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap
import net.minecraft.network.chat.Component
import net.minecraft.world.item.CreativeModeTabs
import net.minecraft.world.item.Item
import net.minecraftforge.common.CreativeModeTabRegistry
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.nullsFirst
import ru.dbotthepony.mc.otm.core.nullsLast
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.matter.MatterManager

object CreativeMenuComparator : Comparator<Item> {
	override fun compare(o1: Item, o2: Item): Int {
		rebuild()
		return item2index.getInt(o1).compareTo(item2index.getInt(o2))
	}

	private val item2index = Reference2IntOpenHashMap<Item>()

	init {
		item2index.defaultReturnValue(Int.MAX_VALUE)
	}

	private fun doRebuild() {
		var i = 0

		for (tab in CreativeModeTabRegistry.getSortedCreativeModeTabs()) {
			for (item in tab.displayItems) {
				item2index.computeIfAbsent(item.item, Reference2IntFunction { i++ })
			}
		}
	}

	private fun rebuild() {
		if (item2index.isEmpty()) {
			doRebuild()

			if (item2index.isEmpty()) {
				val player = minecraft.player ?: return
				// creative tabs were not populated yet
				CreativeModeTabs.tryRebuildTabContents(player.connection.enabledFeatures(), false /* operator tabs */, player.level().registryAccess())

				doRebuild()
			}
		}
	}

	internal fun invalidate() {
		item2index.clear()
	}

	val NullsFirst = nullsFirst()
	val NullsLast = nullsLast()
}

object MatterValueComparator : Comparator<Item> {
	override fun compare(o1: Item, o2: Item): Int {
		return MatterManager.get(o1).matter.compareTo(MatterManager.get(o2).matter)
	}

	val NullsFirst = nullsFirst()
	val NullsLast = nullsLast()
}

object MatterComplexityComparator : Comparator<Item> {
	override fun compare(o1: Item, o2: Item): Int {
		return MatterManager.get(o1).complexity.compareTo(MatterManager.get(o2).complexity)
	}

	val NullsFirst = nullsFirst()
	val NullsLast = nullsLast()
}

object ItemLocalizedNameComparator : Comparator<Item> {
	override fun compare(o1: Item, o2: Item): Int {
		return o1.description.string.compareTo(o2.description.string)
	}

	val NullsFirst = nullsFirst()
	val NullsLast = nullsLast()
}

object ItemModComparator : Comparator<Item> {
	override fun compare(o1: Item, o2: Item): Int {
		val a = o1.registryName?.namespace ?: return 0
		val b = o2.registryName?.namespace ?: return 0
		return a.compareTo(b)
	}

	val NullsFirst = nullsFirst()
	val NullsLast = nullsLast()
}

object ItemIDComparator : Comparator<Item> {
	override fun compare(o1: Item, o2: Item): Int {
		val a = o1.registryName ?: return 0
		val b = o2.registryName ?: return 0
		return a.compareTo(b)
	}

	val NullsFirst = nullsFirst()
	val NullsLast = nullsLast()
}

enum class ItemSorter(val comparator: Comparator<Item?>, private val sTitle: Component) {
	DEFAULT(CreativeMenuComparator.NullsFirst, TranslatableComponent("otm.gui.sorting.default")),
	NAME(ItemLocalizedNameComparator.NullsFirst.thenComparing(CreativeMenuComparator.NullsFirst), TranslatableComponent("otm.gui.sorting.name")),
	ID(ItemIDComparator.NullsFirst.thenComparing(CreativeMenuComparator.NullsFirst), TranslatableComponent("otm.gui.sorting.id")),
	MOD(ItemModComparator.NullsFirst.thenComparing(CreativeMenuComparator.NullsFirst), TranslatableComponent("otm.gui.sorting.modid")),
	MATTER_VALUE(MatterValueComparator.NullsFirst.thenComparing(MatterComplexityComparator.NullsFirst).thenComparing(CreativeMenuComparator.NullsFirst), TranslatableComponent("otm.gui.sorting.matter_value")),
	MATTER_COMPLEXITY(MatterComplexityComparator.NullsFirst.thenComparing(MatterValueComparator.NullsFirst).thenComparing(CreativeMenuComparator.NullsFirst), TranslatableComponent("otm.gui.sorting.matter_complexity")),
	;

	val title: Component get() = sTitle.copy()
}
