package ru.dbotthepony.mc.otm.datagen.recipes

import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.data.recipes.RecipeOutput
import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.world.item.crafting.Ingredient
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.stream
import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.recipe.PainterArmorDyeRecipe
import ru.dbotthepony.mc.otm.recipe.PainterRecipe
import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry
import java.util.function.Consumer

private val Item.recipeName get() = registryName!!.namespace + "/" + registryName!!.path

private fun generate(consumer: RecipeOutput, items: Map<out DyeColor?, Item>, amount: Int = 1) {
	for ((targetColor, targetItem) in items) {
		if (targetColor == null) continue

		consumer.accept(PainterRecipe(
			Ingredient.of(items.entries.stream().filter { it.key != null && it.key != targetColor }.map { ItemStack(it.value) }),
			ItemStack(targetItem),
			mapOf(targetColor to amount)
		).toFinished(modLocation("painter/" + targetItem.recipeName)))
	}
}

private fun generate(consumer: RecipeOutput, default: Item, items: Map<out DyeColor?, Item>, amount: Int = 1, cleaning: Boolean = true) {
	generate(consumer, items)

	if (cleaning)
		cleaning(consumer, default, items)

	for ((k1, v1) in items) {
		if (k1 == null) continue

		consumer.accept(PainterRecipe(
			Ingredient.of(default),
			ItemStack(v1),
			mapOf(k1 to amount)
		).toFinished(modLocation("painter/" + default.recipeName + "/" + v1.recipeName)))
	}
}

private fun cleaning(consumer: RecipeOutput, to: Item, from: Map<out DyeColor?, Item>) {
	consumer.accept(PainterRecipe(
		Ingredient.of(from.entries.stream().filter { it.key != null }.map { ItemStack(it.value) }),
		ItemStack(to),
		mapOf(null to 15)
	).toFinished(modLocation("painter/cleaning/" + to.recipeName)))
}

private fun striped(consumer: RecipeOutput, name: String, items: List<Pair<Item, Pair<DyeColor, DyeColor>>>, base: Map<DyeColor, Item>) {
	for ((stripeItem, colors) in items) {
		val (baseColor, stripe) = colors

		consumer.accept(PainterRecipe(
			Ingredient.of(base[baseColor]),
			ItemStack(stripeItem),
			setOf(stripe)
		).toFinished(modLocation("painter/stripes_$name/${baseColor.getName()}/${stripe.getName()}")))
	}
}

fun addPainterRecipes(consumer: RecipeOutput) {
	generate(consumer, mapOf(
		DyeColor.WHITE to Items.WHITE_WOOL,
		DyeColor.ORANGE to Items.ORANGE_WOOL,
		DyeColor.MAGENTA to Items.MAGENTA_WOOL,
		DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_WOOL,
		DyeColor.YELLOW to Items.YELLOW_WOOL,
		DyeColor.LIME to Items.LIME_WOOL,
		DyeColor.PINK to Items.PINK_WOOL,
		DyeColor.GRAY to Items.GRAY_WOOL,
		DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_WOOL,
		DyeColor.CYAN to Items.CYAN_WOOL,
		DyeColor.PURPLE to Items.PURPLE_WOOL,
		DyeColor.BLUE to Items.BLUE_WOOL,
		DyeColor.BROWN to Items.BROWN_WOOL,
		DyeColor.GREEN to Items.GREEN_WOOL,
		DyeColor.RED to Items.RED_WOOL,
		DyeColor.BLACK to Items.BLACK_WOOL,
	))

	generate(consumer, mapOf(
		DyeColor.WHITE to Items.WHITE_CARPET,
		DyeColor.ORANGE to Items.ORANGE_CARPET,
		DyeColor.MAGENTA to Items.MAGENTA_CARPET,
		DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_CARPET,
		DyeColor.YELLOW to Items.YELLOW_CARPET,
		DyeColor.LIME to Items.LIME_CARPET,
		DyeColor.PINK to Items.PINK_CARPET,
		DyeColor.GRAY to Items.GRAY_CARPET,
		DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_CARPET,
		DyeColor.CYAN to Items.CYAN_CARPET,
		DyeColor.PURPLE to Items.PURPLE_CARPET,
		DyeColor.BLUE to Items.BLUE_CARPET,
		DyeColor.BROWN to Items.BROWN_CARPET,
		DyeColor.GREEN to Items.GREEN_CARPET,
		DyeColor.RED to Items.RED_CARPET,
		DyeColor.BLACK to Items.BLACK_CARPET,
	))

	generate(consumer, mapOf(
		DyeColor.WHITE to Items.WHITE_BED,
		DyeColor.ORANGE to Items.ORANGE_BED,
		DyeColor.MAGENTA to Items.MAGENTA_BED,
		DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_BED,
		DyeColor.YELLOW to Items.YELLOW_BED,
		DyeColor.LIME to Items.LIME_BED,
		DyeColor.PINK to Items.PINK_BED,
		DyeColor.GRAY to Items.GRAY_BED,
		DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_BED,
		DyeColor.CYAN to Items.CYAN_BED,
		DyeColor.PURPLE to Items.PURPLE_BED,
		DyeColor.BLUE to Items.BLUE_BED,
		DyeColor.BROWN to Items.BROWN_BED,
		DyeColor.GREEN to Items.GREEN_BED,
		DyeColor.RED to Items.RED_BED,
		DyeColor.BLACK to Items.BLACK_BED,
	), 3)

	generate(consumer, mapOf(
		DyeColor.WHITE to Items.WHITE_CANDLE,
		DyeColor.ORANGE to Items.ORANGE_CANDLE,
		DyeColor.MAGENTA to Items.MAGENTA_CANDLE,
		DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_CANDLE,
		DyeColor.YELLOW to Items.YELLOW_CANDLE,
		DyeColor.LIME to Items.LIME_CANDLE,
		DyeColor.PINK to Items.PINK_CANDLE,
		DyeColor.GRAY to Items.GRAY_CANDLE,
		DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_CANDLE,
		DyeColor.CYAN to Items.CYAN_CANDLE,
		DyeColor.PURPLE to Items.PURPLE_CANDLE,
		DyeColor.BLUE to Items.BLUE_CANDLE,
		DyeColor.BROWN to Items.BROWN_CANDLE,
		DyeColor.GREEN to Items.GREEN_CANDLE,
		DyeColor.RED to Items.RED_CANDLE,
		DyeColor.BLACK to Items.BLACK_CANDLE,
	))

	generate(consumer, mapOf(
		DyeColor.WHITE to Items.WHITE_CONCRETE,
		DyeColor.ORANGE to Items.ORANGE_CONCRETE,
		DyeColor.MAGENTA to Items.MAGENTA_CONCRETE,
		DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_CONCRETE,
		DyeColor.YELLOW to Items.YELLOW_CONCRETE,
		DyeColor.LIME to Items.LIME_CONCRETE,
		DyeColor.PINK to Items.PINK_CONCRETE,
		DyeColor.GRAY to Items.GRAY_CONCRETE,
		DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_CONCRETE,
		DyeColor.CYAN to Items.CYAN_CONCRETE,
		DyeColor.PURPLE to Items.PURPLE_CONCRETE,
		DyeColor.BLUE to Items.BLUE_CONCRETE,
		DyeColor.BROWN to Items.BROWN_CONCRETE,
		DyeColor.GREEN to Items.GREEN_CONCRETE,
		DyeColor.RED to Items.RED_CONCRETE,
		DyeColor.BLACK to Items.BLACK_CONCRETE,
	))

	generate(consumer, mapOf(
		DyeColor.WHITE to Items.WHITE_CONCRETE_POWDER,
		DyeColor.ORANGE to Items.ORANGE_CONCRETE_POWDER,
		DyeColor.MAGENTA to Items.MAGENTA_CONCRETE_POWDER,
		DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_CONCRETE_POWDER,
		DyeColor.YELLOW to Items.YELLOW_CONCRETE_POWDER,
		DyeColor.LIME to Items.LIME_CONCRETE_POWDER,
		DyeColor.PINK to Items.PINK_CONCRETE_POWDER,
		DyeColor.GRAY to Items.GRAY_CONCRETE_POWDER,
		DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_CONCRETE_POWDER,
		DyeColor.CYAN to Items.CYAN_CONCRETE_POWDER,
		DyeColor.PURPLE to Items.PURPLE_CONCRETE_POWDER,
		DyeColor.BLUE to Items.BLUE_CONCRETE_POWDER,
		DyeColor.BROWN to Items.BROWN_CONCRETE_POWDER,
		DyeColor.GREEN to Items.GREEN_CONCRETE_POWDER,
		DyeColor.RED to Items.RED_CONCRETE_POWDER,
		DyeColor.BLACK to Items.BLACK_CONCRETE_POWDER,
	))

	generate(consumer, MRegistry.CARGO_CRATES.item, MRegistry.CARGO_CRATES.items)
	generate(consumer, MRegistry.TRITANIUM_BLOCK.item, MRegistry.TRITANIUM_BLOCK.items)
	generate(consumer, MRegistry.TRITANIUM_STAIRS.item, MRegistry.TRITANIUM_STAIRS.items)
	generate(consumer, MRegistry.TRITANIUM_SLAB.item, MRegistry.TRITANIUM_SLAB.items)
	generate(consumer, MRegistry.TRITANIUM_WALL.item, MRegistry.TRITANIUM_WALL.items)

	generate(consumer, Items.TERRACOTTA, mapOf(
		DyeColor.WHITE to Items.WHITE_TERRACOTTA,
		DyeColor.ORANGE to Items.ORANGE_TERRACOTTA,
		DyeColor.MAGENTA to Items.MAGENTA_TERRACOTTA,
		DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_TERRACOTTA,
		DyeColor.YELLOW to Items.YELLOW_TERRACOTTA,
		DyeColor.LIME to Items.LIME_TERRACOTTA,
		DyeColor.PINK to Items.PINK_TERRACOTTA,
		DyeColor.GRAY to Items.GRAY_TERRACOTTA,
		DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_TERRACOTTA,
		DyeColor.CYAN to Items.CYAN_TERRACOTTA,
		DyeColor.PURPLE to Items.PURPLE_TERRACOTTA,
		DyeColor.BLUE to Items.BLUE_TERRACOTTA,
		DyeColor.BROWN to Items.BROWN_TERRACOTTA,
		DyeColor.GREEN to Items.GREEN_TERRACOTTA,
		DyeColor.RED to Items.RED_TERRACOTTA,
		DyeColor.BLACK to Items.BLACK_TERRACOTTA,
	), cleaning = false)

	generate(consumer, Items.SHULKER_BOX, mapOf(
		DyeColor.WHITE to Items.WHITE_SHULKER_BOX,
		DyeColor.ORANGE to Items.ORANGE_SHULKER_BOX,
		DyeColor.MAGENTA to Items.MAGENTA_SHULKER_BOX,
		DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_SHULKER_BOX,
		DyeColor.YELLOW to Items.YELLOW_SHULKER_BOX,
		DyeColor.LIME to Items.LIME_SHULKER_BOX,
		DyeColor.PINK to Items.PINK_SHULKER_BOX,
		DyeColor.GRAY to Items.GRAY_SHULKER_BOX,
		DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_SHULKER_BOX,
		DyeColor.CYAN to Items.CYAN_SHULKER_BOX,
		DyeColor.PURPLE to Items.PURPLE_SHULKER_BOX,
		DyeColor.BLUE to Items.BLUE_SHULKER_BOX,
		DyeColor.BROWN to Items.BROWN_SHULKER_BOX,
		DyeColor.GREEN to Items.GREEN_SHULKER_BOX,
		DyeColor.RED to Items.RED_SHULKER_BOX,
		DyeColor.BLACK to Items.BLACK_SHULKER_BOX,
	))

	generate(consumer, Items.GLASS, mapOf(
		DyeColor.WHITE to Items.WHITE_STAINED_GLASS,
		DyeColor.ORANGE to Items.ORANGE_STAINED_GLASS,
		DyeColor.MAGENTA to Items.MAGENTA_STAINED_GLASS,
		DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_STAINED_GLASS,
		DyeColor.YELLOW to Items.YELLOW_STAINED_GLASS,
		DyeColor.LIME to Items.LIME_STAINED_GLASS,
		DyeColor.PINK to Items.PINK_STAINED_GLASS,
		DyeColor.GRAY to Items.GRAY_STAINED_GLASS,
		DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_STAINED_GLASS,
		DyeColor.CYAN to Items.CYAN_STAINED_GLASS,
		DyeColor.PURPLE to Items.PURPLE_STAINED_GLASS,
		DyeColor.BLUE to Items.BLUE_STAINED_GLASS,
		DyeColor.BROWN to Items.BROWN_STAINED_GLASS,
		DyeColor.GREEN to Items.GREEN_STAINED_GLASS,
		DyeColor.RED to Items.RED_STAINED_GLASS,
		DyeColor.BLACK to Items.BLACK_STAINED_GLASS,
	))

	generate(consumer, Items.GLASS_PANE, mapOf(
		DyeColor.WHITE to Items.WHITE_STAINED_GLASS_PANE,
		DyeColor.ORANGE to Items.ORANGE_STAINED_GLASS_PANE,
		DyeColor.MAGENTA to Items.MAGENTA_STAINED_GLASS_PANE,
		DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_STAINED_GLASS_PANE,
		DyeColor.YELLOW to Items.YELLOW_STAINED_GLASS_PANE,
		DyeColor.LIME to Items.LIME_STAINED_GLASS_PANE,
		DyeColor.PINK to Items.PINK_STAINED_GLASS_PANE,
		DyeColor.GRAY to Items.GRAY_STAINED_GLASS_PANE,
		DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_STAINED_GLASS_PANE,
		DyeColor.CYAN to Items.CYAN_STAINED_GLASS_PANE,
		DyeColor.PURPLE to Items.PURPLE_STAINED_GLASS_PANE,
		DyeColor.BLUE to Items.BLUE_STAINED_GLASS_PANE,
		DyeColor.BROWN to Items.BROWN_STAINED_GLASS_PANE,
		DyeColor.GREEN to Items.GREEN_STAINED_GLASS_PANE,
		DyeColor.RED to Items.RED_STAINED_GLASS_PANE,
		DyeColor.BLACK to Items.BLACK_STAINED_GLASS_PANE,
	))

	generate(consumer, MRegistry.INDUSTRIAL_GLASS.item, MRegistry.INDUSTRIAL_GLASS.items)
	generate(consumer, MRegistry.INDUSTRIAL_GLASS_PANE.item, MRegistry.INDUSTRIAL_GLASS_PANE.items)
	generate(consumer, MRegistry.DECORATIVE_CRATE.item, MRegistry.DECORATIVE_CRATE.items)
	generate(consumer, MRegistry.TRITANIUM_PRESSURE_PLATE.item, MRegistry.TRITANIUM_PRESSURE_PLATE.items)
	generate(consumer, MItems.TRITANIUM_DOOR[null]!!, MItems.TRITANIUM_DOOR)
	generate(consumer, MItems.TRITANIUM_TRAPDOOR[null]!!, MItems.TRITANIUM_TRAPDOOR)

	generate(consumer, MRegistry.VENT.item, MRegistry.VENT.items)
	generate(consumer, MRegistry.VENT_ALTERNATIVE.item, MRegistry.VENT_ALTERNATIVE.items)
	generate(consumer, MItems.CARGO_CRATE_MINECARTS[null]!!, MItems.CARGO_CRATE_MINECARTS)

	generate(consumer, MRegistry.UNREFINED_FLOOR_TILES.items)
	generate(consumer, MRegistry.FLOOR_TILES.items)
	generate(consumer, MRegistry.FLOOR_TILES_SLAB.items)
	generate(consumer, MRegistry.FLOOR_TILES_STAIRS.items)

	striped(consumer, "full", MRegistry.TRITANIUM_STRIPED_BLOCK.itemsWithColor, MRegistry.TRITANIUM_BLOCK.items)
	striped(consumer, "stairs", MRegistry.TRITANIUM_STRIPED_STAIRS.itemsWithColor, MRegistry.TRITANIUM_STAIRS.items)
	striped(consumer, "walls", MRegistry.TRITANIUM_STRIPED_WALL.itemsWithColor, MRegistry.TRITANIUM_WALL.items)
	striped(consumer, "slabs", MRegistry.TRITANIUM_STRIPED_SLAB.itemsWithColor, MRegistry.TRITANIUM_SLAB.items)

	for (color in DyeColor.entries) {
		consumer.accept(PainterArmorDyeRecipe(mapOf(color to 1)).toFinished(modLocation("painter/armor_dye_" + color.getName().lowercase())))
	}
	consumer.accept(PainterArmorDyeRecipe(mapOf(null to 15)).toFinished(modLocation("painter/armor_clear_dye")))
}
