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

import net.minecraft.advancements.Advancement
import net.minecraft.advancements.AdvancementRewards
import net.minecraft.advancements.FrameType
import net.minecraft.advancements.RequirementsStrategy
import net.minecraft.advancements.critereon.EntityPredicate
import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.advancements.critereon.MinMaxBounds.Doubles
import net.minecraft.world.entity.EntityType
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraftforge.common.data.ExistingFileHelper
import ru.dbotthepony.mc.otm.datagen.DataGen
import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider
import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.triggers.AndroidBatteryTrigger
import ru.dbotthepony.mc.otm.triggers.AndroidResearchTrigger
import ru.dbotthepony.mc.otm.triggers.AndroidTravelUnderwater
import ru.dbotthepony.mc.otm.triggers.BecomeAndroidDeathTrigger
import ru.dbotthepony.mc.otm.triggers.BecomeAndroidSleepTrigger
import ru.dbotthepony.mc.otm.triggers.BecomeAndroidTrigger
import ru.dbotthepony.mc.otm.triggers.BecomeHumaneTrigger
import ru.dbotthepony.mc.otm.triggers.EnderTeleporterFallDeathTrigger
import ru.dbotthepony.mc.otm.triggers.FallDampenersSaveTrigger
import ru.dbotthepony.mc.otm.triggers.KillAsAndroidTrigger
import ru.dbotthepony.mc.otm.triggers.NanobotsArmorTrigger
import ru.dbotthepony.mc.otm.triggers.ShockwaveDamageMobTrigger
import ru.dbotthepony.mc.otm.triggers.ShockwaveTrigger
import java.util.function.Consumer

fun addAndroidAdvancements(serializer: Consumer<Advancement>, existingFileHelper: ExistingFileHelper, lang: MatteryLanguageProvider) {
	val translation = lang.MultiBuilder("otm.advancements.android")

	val root = AdvancementBuilder()
		.display(
			itemStack = ItemStack(MItems.PILL_ANDROID),
			title = translation.add("root", "Androids and Humans") {
				russian("Андроиды и люди")
			},
			description = translation.add("root.desc", "Can you make out who is cruel machine and who shows empathy?") {
				russian("Сможете ли вы отличить бездушную машину от того, кто показывает сочувствие?")
			},
			showToast = false,
			announceChat = false,
			background = modLocation("textures/block/decorative/metal_beam_top.png")
		)
		.addCriterion("became_android", BecomeAndroidTrigger.instance)
		.save(serializer, modLocation("android/root"), existingFileHelper)

	AdvancementBuilder()
		.parent(root)
		.display(
			itemStack = ItemStack(MItems.ZPM_BATTERY),
			title = translation.add("zpm", "Fully Autonomous") {
				russian("Полностью автономный")
			},
			description = translation.add("zpm.desc", "Use Zero Point Module as internal battery power source. Only eternity is your enemy now") {
				russian("Используйте модуль нулевой точки как внутренний источник питания. Теперь только вечность будет вашим злейшим врагом")
			},
			hidden = true,
			frameType = FrameType.CHALLENGE
		)
		.addCriterion("item", AndroidBatteryTrigger.Instance(ItemPredicate.Builder.item().of(MItems.ZPM_BATTERY).build()))
		.save(serializer, modLocation("android/zpm"), existingFileHelper)

	AdvancementBuilder()
		.parent(root)
		.display(
			itemStack = ItemStack(MItems.QUANTUM_BATTERY),
			title = translation.add("quantum_battery", "Wireless Charged") {
				russian("Беспроводная зарядка")
			},
			description = translation.add("quantum_battery.desc", "Use Quantum Battery as internal battery power source, might as well have Fission Reactor charge other side of the link") {
				russian("Используйте Квантовый Аккумулятор как внутренний источник питания, можно даже подключить другой конец к Реактору Распада")
			},
			hidden = true,
			frameType = FrameType.GOAL
		)
		.requirements(RequirementsStrategy.OR)
		.addCriterion("item0", AndroidBatteryTrigger.Instance(ItemPredicate.Builder.item().of(MItems.QUANTUM_BATTERY).build()))
		.addCriterion("item1", AndroidBatteryTrigger.Instance(ItemPredicate.Builder.item().of(MItems.QUANTUM_CAPACITOR).build()))
		.save(serializer, modLocation("android/quantum_battery"), existingFileHelper)

	AdvancementBuilder()
		.parent(root)
		.display(
			itemStack = ItemStack(MItems.PILL_ANDROID),
			title = translation.add("normal", "Last Sweet Dreams") {
				russian("Последние сновидения")
			},
			description = translation.add("normal.desc", "Become an Android in your dreams, a soulless machine... Or is it?") {
				russian("Превратитесь в андроида во сне, в бездушную машину... Или нет?")
			},
			hidden = true,
		)
		.addCriterion("became_android", BecomeAndroidSleepTrigger.instance)
		.save(serializer, modLocation("android/become_thru_sleep"), existingFileHelper)

	AdvancementBuilder()
		.parent(root)
		.display(
			itemStack = ItemStack(MItems.PILL_ANDROID),
			title = translation.add("death", "The Old Way") {
				russian("Изготовленный по старинке")
			},
			description = translation.add("death.desc", "In event of death, become an Android; Veteran's favorite") {
				russian("Станьте андроидом, будучи умерев; Ветераны оценят")
			},
			hidden = true,
		)
		.addCriterion("became_android", BecomeAndroidDeathTrigger.instance)
		.save(serializer, modLocation("android/become_thru_death"), existingFileHelper)

	AdvancementBuilder()
		.parent(root)
		.display(
			itemStack = ItemStack(MItems.PILL_HUMANE),
			title = translation.add("unandroid", "Feel Humane Again") {
				russian("Вкусить человечность вновь")
			},
			description = translation.add("unandroid.desc", "Become fleshy after being a machine, yet something is still missing that you had before...") {
				russian("Вновь обретите плоть после своей жизни как набор гаек и болтов, но вот чего-то всё равно не хватает, что было при вас с самого начала...")
			},
			hidden = true,
			frameType = FrameType.GOAL
		)
		.addCriterion("become_humane", BecomeHumaneTrigger.instance)
		.save(serializer, modLocation("android/become_humane"), existingFileHelper)

	val attractor = AdvancementBuilder()
		.parent(root)
		.display(
			itemStack = ItemStack(MItems.PHANTOM_ATTRACTOR),
			title = translation.add("phantom_attractor", "Eversleeping Decoy") {
				russian("Фантоматичная приманка")
			},
			description = translation.add("phantom_attractor.desc", "Put together a Phantom Attractor, to be able to fight Phantoms as Android again") {
				russian("Создайте приманщик фантомов, для привлечения фантомов вновь, будучи андроидом")
			},
		)
		.addCriterion("has_item", criterion(MItems.PHANTOM_ATTRACTOR))
		.save(serializer, modLocation("regular/phantom_attractor"), existingFileHelper)

	val researchAnything = AdvancementBuilder()
		.parent(root)
		.display(
			itemStack = ItemStack(MItems.ANDROID_STATION),
			title = translation.add("research_anything", "New Trick") {
				russian("Новый фокус")
			},
			description = translation.add("research_anything.desc", "Research anything as Android") {
				russian("Исследуйте что либо за андроида")
			},
		)
		.addCriterion("research_anything", AndroidResearchTrigger.Instance(null))
		.save(serializer, modLocation("android/research_anything"), existingFileHelper)

	AdvancementBuilder()
		.parent(researchAnything)
		.display(
			itemStack = ItemStack(Items.WATER_BUCKET),
			title = translation.add("air_bags", "Patching Up Wooden Vessel") {
				russian("В бочку - затычку")
			},
			description = translation.add("air_bags.desc", "Research Air Bags as Android, to float in water") {
				russian("Исследуйте воздушные мешки, дабы быть вновь поплавком в воде")
			},
		)
		.addCriterion("air_bags", AndroidResearchTrigger.Instance(modLocation(MNames.AIR_BAGS)))
		.save(serializer, modLocation("android/research_air_bags"), existingFileHelper)

	AdvancementBuilder()
		.parent(researchAnything)
		.display(
			itemStack = ItemStack(Items.ENDER_EYE),
			title = translation.add("night_vision", "Second Pair of Eyes") {
				russian("Вторая пара глаз")
			},
			description = translation.add("night_vision.desc", "Research Night Vision as Android, to see in the dark") {
				russian("Исследуйте ночное зрение за андроида, дабы видеть во темноте")
			},
		)
		.addCriterion("night_vision", AndroidResearchTrigger.Instance(modLocation(MNames.NIGHT_VISION)))
		.save(serializer, modLocation("android/research_night_vision"), existingFileHelper)

	val nanobots = AdvancementBuilder()
		.parent(researchAnything)
		.display(
			itemStack = ItemStack(MItems.MATTER_TRANSFORM_MATRIX),
			title = translation.add("nanobots", "Nanomachines, son.") {
				russian("Наномашины, сынок.")
			},
			description = translation.add("nanobots.desc", "Research Nanobots as Android, to unlock potent research that come after it") {
				russian("Исследуйте наномашины за андроида, для разблокировки очень больших возможностей")
			},
			hidden = true
		)
		.addCriterion("nanobots", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS)))
		.save(serializer, modLocation("android/research_nanobots"), existingFileHelper)

	val shielding = AdvancementBuilder()
		.parent(nanobots)
		.display(
			itemStack = ItemStack(Items.SHIELD),
			title = translation.add("nanobots_armor_deflect", "Like a Concrete Wall") {
				russian("Как за каменной стеной")
			},
			description = translation.add("nanobots_armor_deflect.desc", "Have Nanobots absorb more than 5 hears of damage while you are left still functioning") {
				russian("Дайте наноботам поглотить 5 сердец урона, не отключившись насовсем")
			},
			hidden = true,
			frameType = FrameType.GOAL
		)
		.addCriterion("damage", NanobotsArmorTrigger.Instance(Doubles.atLeast(10.0)))
		.save(serializer, modLocation("android/nanobots_armor_deflect"), existingFileHelper)

	AdvancementBuilder()
		.parent(shielding)
		.display(
			itemStack = ItemStack(Items.SHIELD),
			title = translation.add("nanobots_armor_deflect2", "Unstoppable Force vs Immovable Object") {
				russian("Неостановимая сила против недвижимого объекта")
			},
			description = translation.add("nanobots_armor_deflect2.desc", "Have Nanobots absorb more than 10 hears of damage while you are left still functioning") {
				russian("Дайте наноботам поглотить 10 сердец урона, не отключившись насовсем")
			},
			hidden = true,
			frameType = FrameType.CHALLENGE
		)
		.addCriterion("damage", NanobotsArmorTrigger.Instance(Doubles.atLeast(20.0)))
		.save(serializer, modLocation("android/nanobots_armor_deflect2"), existingFileHelper)

	AdvancementBuilder()
		.parent(researchAnything)
		.display(
			itemStack = ItemStack(Items.FEATHER),
			title = translation.add("fall_dampeners_save", "Lucky Landing") {
				russian("Удачное приземление")
			},
			description = translation.add("fall_dampeners_save.desc", "Survive fall that would have otherwise be fatal without Fall Dampeners") {
				russian("Выживите после падения, которое было бы фатальным без поглотителей инерции")
			},
			frameType = FrameType.GOAL
		)
		.addCriterion("saved", FallDampenersSaveTrigger.instance)
		.save(serializer, modLocation("android/fall_dampeners_save"), existingFileHelper)

	AdvancementBuilder()
		.parent(researchAnything)
		.display(
			itemStack = ItemStack(Items.SKELETON_SKULL),
			title = translation.add("ender_teleport_fall_death", "Navigation Error") {
				russian("Ошибка навигации")
			},
			description = translation.add("ender_teleport_fall_death.desc", "Fall to your demise moments after Teleporting as Android") {
				russian("Разбейтесь насмерть через мгновения после телепортации за андроида")
			},
			frameType = FrameType.GOAL,
			hidden = true
		)
		.addCriterion("death", EnderTeleporterFallDeathTrigger.instance)
		.save(serializer, modLocation("android/ender_teleport_fall_death"), existingFileHelper)

	val regen = AdvancementBuilder()
		.parent(nanobots)
		.display(
			itemStack = ItemStack(Items.GOLDEN_APPLE),
			title = translation.add("regen", "Field Repair Done Easy") {
				russian("Починка на ходу - легко")
			},
			description = translation.add("regen.desc", "Research Nanobots Regeneration as Android") {
				russian("Исследуйте регенерацию наноботов за андроида")
			},
		)
		.addCriterion("regen0", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_1)))
		.save(serializer, modLocation("android/regen"), existingFileHelper)

	AdvancementBuilder()
		.parent(regen)
		.display(
			itemStack = ItemStack(Items.ENCHANTED_GOLDEN_APPLE),
			title = translation.add("regen_all", "Field Repair Done Effortless") {
				russian("Починка на ходу - без усилий")
			},
			description = translation.add("regen_all.desc", "Max out Nanobots Regeneration research") {
				russian("Полностью исследуйте регенерацию наноботов за андроида")
			},
			frameType = FrameType.GOAL,
		)
		.addCriterion("regen0", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_1)))
		.addCriterion("regen1", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_2)))
		.addCriterion("regen2", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_3)))
		.addCriterion("regen3", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_4)))
		.save(serializer, modLocation("android/regen_all"), existingFileHelper)

	AdvancementBuilder()
		.parent(researchAnything)
		.display(
			itemStack = ItemStack(MItems.ANDROID_STATION),
			title = translation.add("research_all", "Mecha-Agnomination") {
				russian("Меха-зумие")
			},
			description = translation.add("research_all.desc", "Research everything as Android (that don't block or get blocked by any other research)") {
				russian("Исследуйте все технологии за андроида (которые не блокируют и не блокируются другими технологиями)")
			},
			frameType = FrameType.CHALLENGE
		)
		.rewards(AdvancementRewards.Builder.experience(400).addLootTable(modLocation("research_all_android")))
		.also { advancement ->
			DataGen.researchProvider.generatedView.stream()
				.filter { it.allBlockedBy.isEmpty() && it.allBlocking.isEmpty() }
				.forEach {
					advancement.addCriterion(it.id.toString(), AndroidResearchTrigger.Instance(it))
				}
		}
		.save(serializer, modLocation("android/research_everything"), existingFileHelper)

	val shockwave = AdvancementBuilder()
		.parent(researchAnything)
		.display(
			itemStack = ItemStack(Items.PISTON),
			title = translation.add("shockwave", "Supersonic Landing") {
				russian("Сверхзвуковое приземление")
			},
			description = translation.add("shockwave.desc", "Make a Shockwave upon landing") {
				russian("Вызовите ударную волну при приземлении")
			},
		)
		.addCriterion("shockwave", ShockwaveTrigger.instance)
		.save(serializer, modLocation("android/shockwave"), existingFileHelper)

	AdvancementBuilder()
		.parent(shockwave)
		.display(
			itemStack = ItemStack(Items.WARDEN_SPAWN_EGG),
			title = translation.add("shockwave_warden", "Music to their Ears") {
				russian("Музыка для их ушей")
			},
			description = translation.add("shockwave_warden.desc", "Hurt Warden using Shockwave ability") {
				russian("Нанесите хранителю урон используя ударную волну")
			},
			frameType = FrameType.GOAL
		)
		.addCriterion("shockwave_warden", ShockwaveDamageMobTrigger.Instance(EntityPredicate.Builder.entity().of(EntityType.WARDEN).build().wrap()))
		.save(serializer, modLocation("android/shockwave_warden"), existingFileHelper)

	AdvancementBuilder()
		.parent(root)
		.display(
			itemStack = ItemStack(Items.WITHER_SKELETON_SKULL),
			title = translation.add("wither", "Not Quite Alive, Not Quite Undead") {
				russian("Ни живой, ни мёртвый")
			},
			description = translation.add("wither.desc", "Defeat The Wither as Android. The Wither was surely confused over kind of thing you are") {
				russian("Победите Иссушителя будучи андроидом. Наверняка Иссушитель был ошеломлён таким раскладом дел")
			},
			frameType = FrameType.GOAL,
			hidden = true
		)
		.addCriterion("kill_wither", KillAsAndroidTrigger.Instance(
			predicate = EntityPredicate.Builder.entity().of(EntityType.WITHER).build().wrap(),
		))
		.save(serializer, modLocation("android/wither"), existingFileHelper)

	val underwater = AdvancementBuilder()
		.parent(root)
		.display(
			itemStack = ItemStack(Items.TURTLE_SPAWN_EGG),
			title = translation.add("travel_underwater", "Underwater Walk") {
				russian("Подводная прогулка")
			},
			description = translation.add("travel_underwater.desc", "Travel at least 200 meters underwater as Android without Air Bags research. This reminds us of someone...") {
				russian("Преодолейте как минимум 200 метров под водой будучи андроидом без исследования воздушных мешков. Кого-то это нам напоминает...")
			},
			frameType = FrameType.GOAL,
			hidden = true
		)
		.addCriterion("travel", AndroidTravelUnderwater.Instance(200.0))
		.save(serializer, modLocation("android/underwater"), existingFileHelper)

	AdvancementBuilder()
		.parent(underwater)
		.display(
			itemStack = ItemStack(Items.TURTLE_SPAWN_EGG),
			title = translation.add("travel_underwater2", "Underwater Travel") {
				russian("Подводная прогулка")
			},
			description = translation.add("travel_underwater2.desc", "Travel at least 1046 meters underwater as Android without Air Bags research, like someone else did so") {
				russian("Преодолейте как минимум 1046 метров под водой будучи андроидом без исследования воздушных мешков, прям как тот, кто так однажды так и сделал")
			},
			frameType = FrameType.CHALLENGE,
			hidden = true
		)
		.addCriterion("travel", AndroidTravelUnderwater.Instance(1046.0))
		.save(serializer, modLocation("android/underwater2"), existingFileHelper)

	AdvancementBuilder()
		.parent(root)
		.display(
			itemStack = ItemStack(Items.PRISMARINE_CRYSTALS),
			title = translation.add("elder_guardian", "Drowned, but Still Determined") {
				russian("Затонувший, но всё ещё целеустремлённый")
			},
			description = translation.add("elder_guardian.desc", "Slay Elder Guardian as Android without Air Bags researched") {
				russian("Победите Древнего стража будучи андроидом без исследования воздушных мешков")
			},
			frameType = FrameType.CHALLENGE,
			hidden = true
		)
		.addCriterion("kill_elder_guardian", KillAsAndroidTrigger.Instance(
			predicate = EntityPredicate.Builder.entity().of(EntityType.ELDER_GUARDIAN).build().wrap(),
			featurePredicate = KillAsAndroidTrigger.Not(KillAsAndroidTrigger.Has(AndroidFeatures.AIR_BAGS.registryName!!))
		))
		.save(serializer, modLocation("android/elder_guardian"), existingFileHelper)
}
