package ru.dbotthepony.mc.otm.registry

import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.CreativeModeTab
import net.minecraft.world.item.CreativeModeTabs
import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.material.Fluids
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.event.BuildCreativeModeTabContentsEvent
import net.minecraftforge.eventbus.api.IEventBus
import net.minecraftforge.fluids.FluidStack
import net.minecraftforge.fluids.capability.IFluidHandler
import net.minecraftforge.registries.DeferredRegister
import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.capability.matter.matter
import ru.dbotthepony.mc.otm.capability.matteryEnergy
import ru.dbotthepony.mc.otm.core.util.CreativeMenuComparator
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.registry.MItems.BATTERY_CREATIVE

private fun CreativeModeTab.Output.accept(values: Collection<Item>) {
	for (item in values) {
		accept(item)
	}
}

private fun CreativeModeTab.Output.base(values: Map<DyeColor?, Item>) {
	accept(values[null]!!)
}

private val colorOrder = listOf(
	null,
	DyeColor.WHITE,
	DyeColor.ORANGE,
	DyeColor.MAGENTA,
	DyeColor.LIGHT_BLUE,
	DyeColor.YELLOW,
	DyeColor.LIME,
	DyeColor.PINK,
	DyeColor.GRAY,
	DyeColor.LIGHT_GRAY,
	DyeColor.CYAN,
	DyeColor.PURPLE,
	DyeColor.BLUE,
	DyeColor.BROWN,
	DyeColor.GREEN,
	DyeColor.RED,
	DyeColor.BLACK,
)

private fun CreativeModeTab.Output.colored(values: Map<out DyeColor?, Item>) {
	accept(values[DyeColor.WHITE]!!)
	accept(values[DyeColor.ORANGE]!!)
	accept(values[DyeColor.MAGENTA]!!)
	accept(values[DyeColor.LIGHT_BLUE]!!)
	accept(values[DyeColor.YELLOW]!!)
	accept(values[DyeColor.LIME]!!)
	accept(values[DyeColor.PINK]!!)
	accept(values[DyeColor.GRAY]!!)
	accept(values[DyeColor.LIGHT_GRAY]!!)
	accept(values[DyeColor.CYAN]!!)
	accept(values[DyeColor.PURPLE]!!)
	accept(values[DyeColor.BLUE]!!)
	accept(values[DyeColor.BROWN]!!)
	accept(values[DyeColor.GREEN]!!)
	accept(values[DyeColor.RED]!!)
	accept(values[DyeColor.BLACK]!!)
}

private fun CreativeModeTab.Output.all(values: Map<DyeColor?, Item>) {
	base(values)
	colored(values)
}

private fun CreativeModeTab.Output.energized(value: Item) {
	accept(value)

	val stack = ItemStack(value, 1)
	val energy = stack.matteryEnergy ?: throw IllegalArgumentException("${value.registryName} does not implement mattery energy capability")
	energy.fillBattery()

	if (ItemStack(value, 1).matteryEnergy!!.batteryLevel != energy.batteryLevel)
		accept(stack)
}

private fun CreativeModeTab.Output.energized(values: Iterable<Item>) {
	for (value in values) {
		energized(value)
	}
}

private fun CreativeModeTab.Output.mattery(value: Item) {
	accept(value)

	val stack = ItemStack(value, 1)
	val matter = stack.matter ?: throw IllegalArgumentException("${value.registryName} does not implement matter capability")

	matter.fillMatter()

	if (ItemStack(value, 1).matter!!.storedMatter != matter.storedMatter)
		accept(stack)
}

private fun CreativeModeTab.Output.mattery(values: Iterable<Item>) {
	for (value in values) {
		mattery(value)
	}
}

private fun CreativeModeTab.Output.fluids(value: Item) {
	accept(value)

	for (fluid in ForgeRegistries.FLUIDS.values) {
		if (fluid != Fluids.EMPTY && fluid.isSource(fluid.defaultFluidState())) {
			accept(ItemStack(value, 1).also {
				it.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).ifPresentK {
					it.fill(FluidStack(fluid, it.getTankCapacity(0)), IFluidHandler.FluidAction.EXECUTE)
				}
			})
		}
	}
}

private fun addMainCreativeTabItems(consumer: CreativeModeTab.Output) {
	with(consumer) {
		accept(MItems.MACHINES)
		accept(MItems.CreativeUpgrades.LIST)

		accept(MRegistry.CARGO_CRATES.item)
		accept(MItems.HOLO_SIGN)

		base(MItems.TRITANIUM_DOOR)
		base(MItems.TRITANIUM_TRAPDOOR)
		accept(MRegistry.TRITANIUM_PRESSURE_PLATE.item)
		accept(MItems.TRITANIUM_ANVIL[0])

		// accept(MItems.MATTER_DUST)

		accept(MItems.TRITANIUM_ORE)
		accept(MItems.DEEPSLATE_TRITANIUM_ORE)
		accept(MItems.TRITANIUM_ORE_CLUMP)
		accept(MItems.TRITANIUM_DUST)
		accept(MItems.TRITANIUM_NUGGET)
		accept(MItems.TRITANIUM_INGOT)
		accept(MItems.TRITANIUM_INGOT_BLOCK)

		accept(MItems.TRITANIUM_TOOLS)
		accept(MItems.TRITANIUM_SHIELD)
		accept(MItems.SIMPLE_TRITANIUM_ARMOR)
		accept(MItems.TRITANIUM_ARMOR)

		energized(MItems.ENERGY_SWORD)
		energized(MItems.PLASMA_RIFLE)

		accept(MItems.EXPLOSIVE_HAMMER)
		accept(ItemStack(MItems.EXPLOSIVE_HAMMER).also { MItems.EXPLOSIVE_HAMMER.prime(it) })

		accept(MItems.BLACK_HOLE_SCANNER)
		accept(MItems.GRAVITATION_FIELD_LIMITER)
		accept(MItems.GRAVITATION_FIELD_SENSOR)
		accept(MItems.PORTABLE_GRAVITATION_STABILIZER)
		accept(MItems.BLACK_HOLE)
		accept(MItems.GRAVITATIONAL_DISRUPTOR)

		accept(MItems.ESSENCE_SERVO)

		energized(MItems.ALL_BATTERIES)
		mattery(MItems.MATTER_CAPACITORS)
		accept(MItems.PATTERN_DRIVE_NORMAL)
		accept(MItems.PATTERN_DRIVE_CREATIVE)
		accept(MItems.PATTERN_DRIVE_CREATIVE2)

		fluids(MItems.FLUID_CAPSULE)
		fluids(MItems.FLUID_TANK)

		base(MItems.CARGO_CRATE_MINECARTS)

		accept(MItems.NUTRIENT_PASTE)

		// exo
		accept(MItems.EXOPACK_PROBE)
		accept(MItems.ExopackUpgrades.INVENTORY_UPGRADE_CREATIVE)
		accept(MItems.ExopackUpgrades.CRAFTING_UPGRADE)
		accept(MItems.ExopackUpgrades.SMELTING_UPGRADE)

		accept(MItems.ExopackUpgrades.INVENTORY_UPGRADE_BIG)
		accept(MItems.ExopackUpgrades.INVENTORY_UPGRADE_HUGE)
		accept(MItems.ExopackUpgrades.INVENTORY_UPGRADE_WITHER)
		accept(MItems.ExopackUpgrades.INVENTORY_UPGRADE_ENDER_DRAGON)

		accept(MItems.ExopackUpgrades.INVENTORY_UPGRADES)
		// /exo

		accept(MItems.PILLS)

		accept(MItems.COMPONENTS)
	}
}

private fun addDecorativeTabItems(consumer: CreativeModeTab.Output) {
	with(consumer) {
		accept(MItems.LABORATORY_LAMP)
		accept(MItems.LABORATORY_LAMP_INVERTED)
		accept(MItems.DANGER_STRIPE_BLOCK)
		accept(MItems.METAL_BEAM)
		accept(MItems.ENGINE)

		accept(MItems.TRITANIUM_STRIPED_BLOCK)
		accept(MItems.TRITANIUM_STRIPED_STAIRS)
		accept(MItems.TRITANIUM_STRIPED_SLAB)
		accept(MItems.TRITANIUM_STRIPED_WALL)
		accept(MItems.CARBON_FIBRE_BLOCK)
		accept(MItems.METAL_JUNK)
		accept(MItems.METAL_MESH)

		accept(MItems.TRITANIUM_BARS)

		colored(MItems.TRITANIUM_DOOR)
		colored(MItems.TRITANIUM_TRAPDOOR)
		accept(MRegistry.TRITANIUM_PRESSURE_PLATE.items.values)

		for (i in 0 until MItems.TRITANIUM_ANVIL.size)
			accept(MItems.TRITANIUM_ANVIL[i])

		colored(MRegistry.CARGO_CRATES.items)

		colored(MItems.CARGO_CRATE_MINECARTS)

		all(MRegistry.DECORATIVE_CRATE.allItems)

		for (color in colorOrder) {
			accept(MRegistry.TRITANIUM_BLOCK.allItems[color]!!)
			accept(MRegistry.TRITANIUM_STAIRS.allItems[color]!!)
			accept(MRegistry.TRITANIUM_SLAB.allItems[color]!!)
			accept(MRegistry.TRITANIUM_WALL.allItems[color]!!)
		}

		all(MRegistry.INDUSTRIAL_GLASS.allItems)
		all(MRegistry.INDUSTRIAL_GLASS_PANE.allItems)

		colored(MRegistry.UNREFINED_FLOOR_TILES.items)
		colored(MRegistry.FLOOR_TILES.items)
		colored(MRegistry.FLOOR_TILES_STAIRS.items)
		colored(MRegistry.FLOOR_TILES_SLAB.items)

		all(MRegistry.VENT.allItems)
		all(MRegistry.VENT_ALTERNATIVE.allItems)

		accept(MRegistry.TRITANIUM_STRIPED_BLOCK.flatItems)
		accept(MRegistry.TRITANIUM_STRIPED_STAIRS.flatItems)
		accept(MRegistry.TRITANIUM_STRIPED_SLAB.flatItems)
		accept(MRegistry.TRITANIUM_STRIPED_WALL.flatItems)
	}
}

object MCreativeTabs {
	private val registry = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, OverdriveThatMatters.MOD_ID)

	val MAIN: CreativeModeTab by registry.register("main") {
		CreativeModeTab.builder()
			.title(TranslatableComponent("itemGroup.otm"))
			.icon { ItemStack(BATTERY_CREATIVE, 1) }
			.withTabsBefore(CreativeModeTabs.SPAWN_EGGS)
			.build()
	}

	val DECORATIVE: CreativeModeTab by registry.register("decorative") {
		CreativeModeTab.builder()
			.title(TranslatableComponent("itemGroup.otm_decorative"))
			.icon { ItemStack(MRegistry.VENT.item, 1) }
			.withTabsBefore(ResourceLocation(OverdriveThatMatters.MOD_ID, "main"))
			.build()
	}

	internal fun initialize(bus: IEventBus) {
		registry.register(bus)
	}

	fun register(event: BuildCreativeModeTabContentsEvent) {
		CreativeMenuComparator.invalidate()

		when (event.tab) {
			MAIN -> addMainCreativeTabItems(event)
			DECORATIVE -> addDecorativeTabItems(event)
		}
	}
}
