package ru.dbotthepony.mc.otm.datagen.advancements

import net.minecraft.advancements.AdvancementHolder
import net.minecraft.advancements.AdvancementRequirements
import net.minecraft.advancements.AdvancementType
import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.key
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider
import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.registry.game.MItems
import ru.dbotthepony.mc.otm.triggers.TakeItemOutOfReplicatorTrigger
import java.util.function.Consumer

data class CraftEntry(
	val item: Collection<Item>,
	val englishName: String,
	val englishSuffix: String? = null,

	val russianName: String? = null,
	val russianSuffix: String? = null,
) {
	constructor(
		item: Item,
		englishName: String,
		englishSuffix: String? = null,
		russianName: String? = null,
		russianSuffix: String? = null,
	) : this(listOf(item), englishName, englishSuffix, russianName, russianSuffix)

	fun make(serializer: Consumer<AdvancementHolder>, parent: AdvancementHolder, translation: MatteryLanguageProvider.MultiBuilder): AdvancementHolder {
		val path = item.first().registryName!!.path

		val translated = translation.add("$path.desc", "Craft a %s%s") {
			russian("Создайте %s%s")
		}

		val translatedSuffix = translation.add("$path.suffix", if (englishSuffix != null) ". $englishSuffix" else "") {
			russian(if (russianSuffix != null) ". $russianSuffix" else "")
		}

		return AdvancementBuilder()
			.parent(parent)
			.display(
				itemStack = ItemStack(item.first()),
				title = translation.add(path, englishName) {
					if (russianName != null) {
						russian(russianName)
					}
				},
				description = TranslatableComponent(translated.contents.key, item.first().description, translatedSuffix),
			)
			.also {
				for ((i, item) in item.withIndex()) {
					it.addCriterion(i.toString(), criterion(item))
				}
			}
			.requirements(AdvancementRequirements.Strategy.OR)
			.save(serializer, modLocation("machines/$path"))
	}
}

fun addMachineAdvancements(serializer: Consumer<AdvancementHolder>, lang: MatteryLanguageProvider, root: AdvancementHolder) {
	val translation = lang.MultiBuilder("otm.advancements.machine")

	val chem = AdvancementBuilder()
		.parent(root)
		.display(
			itemStack = ItemStack(MItems.CHEMICAL_GENERATOR[null]!!),
			title = translation.add("chemical_generator", "Burning the Organics") {
				russian("Сжигание органики")
			},
			description = translation.add("chemical_generator.desc", "Craft a Chemical Generator, better to put it outside") {
				russian("Создайте химический генератор. Лучше установить его снаружи")
			},
		)
		.also {
			for ((i, v) in MItems.CHEMICAL_GENERATOR.values.withIndex())
				it.addCriterion("has_machine_$i", criterion(v))
		}
		.requirements(AdvancementRequirements.Strategy.OR)
		.save(serializer, modLocation("machines/chemical_generator"))

	val press = AdvancementBuilder()
		.parent(chem)
		.display(
			itemStack = ItemStack(MItems.TWIN_PLATE_PRESS[null]!!),
			title = translation.add("plate_press", "Bending the Material") {
				russian("Раскатка металла")
			},
			description = translation.add("plate_press.desc", "Craft a Plate Press, avoid having limbs inside at all times") {
				russian("Создайте пресс пластин, не суйте свои или чужие конечности внутрь")
			},
		)
		.also {
			for ((i, m) in MItems.TWIN_PLATE_PRESS.values.withIndex())
				it.addCriterion(i.toString(), criterion(m))
		}
		.requirements(AdvancementRequirements.Strategy.OR)
		.save(serializer, modLocation("machines/plate_press"))

	CraftEntry(
		MItems.ENERGY_SERVO.values, "Power Goes In, Powered Things Go Out",
		russianName = "Энергия на вход, электроинструмент на выход").make(serializer, press, translation)

	val scanner = CraftEntry(
		MItems.MATTER_SCANNER.values, "Scanning Things that Matter",
		russianName = "Сканируем вещи которые материальны")
	val decomposer = CraftEntry(
		MItems.MATTER_DECOMPOSER.values, "Decaying the Atoms", "Keep your limbs outside of the working chamber at all times",
		russianName = "Разлагаем атомы", russianSuffix = "Во всех ситуациях держите свои конечности вне рабочей камеры")
	val panel = CraftEntry(
		MItems.MATTER_PANEL.values, "Indexing the Library",
		russianName = "Индексируем библиотеку")
	val replicator = CraftEntry(
		MItems.MATTER_REPLICATOR.values, "Cook with (Im)Perfection", "Now let's bake some perfect bread",
		russianName = "Повар с (не) идеальностями", russianSuffix = "А теперь давайте выпечем немного идеального хлеба")
	val bottler = CraftEntry(
		MItems.MATTER_BOTTLER.values, "Transfusing Pure Matter", "For those who loved to play with water in their childhood",
		russianName = "Переливаем чистую материю", russianSuffix = "Для тех, кто любил играться в воде в детстве")
	val recycler = CraftEntry(
		MItems.MATTER_RECYCLER.values, "Refine and Redefine", "This is what waste recycling should look like",
		russianName = "Переработка и перегонка", russianSuffix = "Вот он, пик переработки отходов")
	val capacitor = CraftEntry(
		MItems.MATTER_CAPACITOR_BANK.values, "Modular Matter Tank",
		russianName = "Модульный бак материи")

	val counter = CraftEntry(
		MItems.ENERGY_COUNTER.values, "Visualize Power Burn",
		russianName = "Визуализация сжигания энергии")
	val battery = CraftEntry(
		MItems.BATTERY_BANK.values, "Batteries Not Included", "By all means avoid the urge to hammer incompatible batteries into the power bus.",
		russianName = "Батарейки в комплект не входят", russianSuffix = "Пожалуйста, воздержитесь от вбивания кувалдой несовместимых батарей в энергетическую шину.")

	val pattern = CraftEntry(
		MItems.PATTERN_STORAGE, "Digital Knowledge Library",
		russianName = "Цифровая библиотека знаний")

	val reconstructor = CraftEntry(
		MItems.MATTER_RECONSTRUCTOR.values, "Flipping Hourglass",
		russianName = "Переворачиваем песочные часы")

	decomposer.make(serializer, press, translation).also {
		pattern.make(serializer, it, translation).also {
			scanner.make(serializer, it, translation)
			panel.make(serializer, it, translation)

			replicator.make(serializer, it, translation).also {
				AdvancementBuilder()
					.parent(it)
					.display(
						itemStack = ItemStack(Items.BREAD),
						title = translation.add("replicate_something", "Local Bakery") {
							russian("Местная выпечка")
						},
						description = translation.add("replicate_something.desc", "Replicate something using Matter Replicator. If you replicated some food, be first to taste it among your company") {
							russian("Среплицируйте что либо используя репликатор материи. Если это еда, то не стесняйтесь быть первым, кто попробует её на вкус среди вашей компании")
						},
						frameType = AdvancementType.GOAL
					)
					.addCriterion("replicate_something", TakeItemOutOfReplicatorTrigger.Instance(ItemPredicate.Builder.item().of(
						MItems.MATTER_DUST).build(), true).criterion())
					.save(serializer, modLocation("machines/replicate_something"))

				AdvancementBuilder()
					.parent(it)
					.display(
						hidden = true,
						itemStack = ItemStack(MItems.MATTER_DUST),
						title = translation.add("replicate_failure", "Unhealthy Flavor") {
							russian("Вредная посыпка")
						},
						description = translation.add("replicate_failure.desc", "Experience replication failure and have your thing turn into matter dust") {
							russian("Наблюдайте неудачный результат репликации, где ваш заказ рассыпался в материальную труху")
						},
					)
					.addCriterion("replicate_failure", TakeItemOutOfReplicatorTrigger.Instance(ItemPredicate.Builder.item().of(
						MItems.MATTER_DUST).build()).criterion())
					.save(serializer, modLocation("machines/replicate_failure"))
			}

			reconstructor.make(serializer, it, translation)
		}

		bottler.make(serializer, it, translation)
		recycler.make(serializer, it, translation)
		capacitor.make(serializer, it, translation)
	}

	counter.make(serializer, press, translation).also {
		battery.make(serializer, it, translation)
	}

	val station = CraftEntry(
		MItems.ANDROID_STATION.values, "Android Home Page",
		russianName = "Домашняя страница андроидов",
		russianSuffix = "Только пользоваться этим устройством могут вёдра с болтами",
		englishSuffix = "Except only buckets of bolts can use this thing")

	val charger = CraftEntry(
		MItems.ANDROID_CHARGER.values, "Android Home Router",
		russianName = "Домашняя страница андроидов")

	station.make(serializer, press, translation).also {
		charger.make(serializer, it, translation)
	}

	CraftEntry(
		MItems.COBBLESTONE_GENERATOR.values, "Cobblestone: Infinity + 1",
		russianName = "Булыжник: бесконечность + 1",
		russianSuffix = "Смотрите, чтоб он не просыпался во все сундуки",
		englishSuffix = "Watch for not to spill it over all your chests").make(serializer, press, translation)

		.also {
			CraftEntry(
				MItems.INFINITE_WATER_SOURCE, "We Got A Leak!",
				russianName = "У нас утечка!",
				russianSuffix = "Как это вообще возможно!?",
				englishSuffix = "How is that even possible!?")
				.make(serializer, it, translation)
		}

	CraftEntry(
		MItems.POWERED_FURNACE.values, "One Big Resistor",
		russianName = "Один большой резистор",
		russianSuffix = "Каждый элемент электрической цепи способен испускать свет и тепло, единожды.",
		englishSuffix = "Any electrical element can emit light and heat, once.")
		.make(serializer, press, translation)
	.also {
		CraftEntry(
			MItems.POWERED_BLAST_FURNACE.values, "Big Microwave Oven",
			russianName = "Большая микроволновая печь").make(serializer, it, translation)

		CraftEntry(
			MItems.POWERED_SMOKER.values, "Small Microwave Oven",
			russianName = "Маленькая микроволновая печь").make(serializer, it, translation)
	}
}
