package ru.dbotthepony.mc.otm.datagen.blocks

import net.minecraft.world.level.block.state.properties.BlockStateProperties
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf
import net.minecraftforge.client.model.generators.ConfiguredModel
import ru.dbotthepony.mc.otm.block.CableBlock
import ru.dbotthepony.mc.otm.block.decorative.CargoCrateBlock
import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.block.matter.MatterBottlerBlock
import ru.dbotthepony.mc.otm.block.tech.AndroidChargerBlock
import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom
import ru.dbotthepony.mc.otm.core.math.xRotationBlockstateNorth
import ru.dbotthepony.mc.otm.core.math.xRotationBlockstateSouth
import ru.dbotthepony.mc.otm.core.math.yRotationBlockstateNorth
import ru.dbotthepony.mc.otm.core.math.yRotationBlockstateSouth
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.registry.MRegistry

fun addBlockStates(provider: MatteryBlockStateProvider) {
	provider.block(MBlocks.BLACK_HOLE)
	provider.block(MBlocks.ANDROID_STATION)

	provider.ore(MBlocks.DEEPSLATE_TRITANIUM_ORE)
	provider.ore(MBlocks.TRITANIUM_ORE)
	provider.ore(MBlocks.TRITANIUM_RAW_BLOCK)
	provider.block(MBlocks.TRITANIUM_INGOT_BLOCK)
	provider.block(MBlocks.METAL_MESH)

	provider.block(MBlocks.CHEMICAL_GENERATOR)
	provider.block(MBlocks.MATTER_SCANNER)
	provider.block(MBlocks.ITEM_MONITOR)
	provider.block(MBlocks.HOLO_SIGN)

	provider.exec {
		with(provider.getMultipartBuilder(MBlocks.PHANTOM_ATTRACTOR)) {
			for (dir in BlockRotationFreedom.ONE.possibleValues) {
				part().modelFile(provider.models().getExistingFile(modLocation("block/${MNames.PHANTOM_ATTRACTOR}")))
					.rotationY(dir.front.yRotationBlockstateNorth())
					.addModel()
					.condition(BlockStateProperties.DOUBLE_BLOCK_HALF, DoubleBlockHalf.LOWER)
					.condition(BlockRotationFreedom.ONE.property, dir)
					.end()
			}
		}

		with(provider.getMultipartBuilder(MBlocks.ANDROID_CHARGER)) {
			for (dir in BlockRotationFreedom.ONE.possibleValues) {
				for (part in AndroidChargerBlock.PART.possibleValues) {
					part().modelFile(provider.models().getExistingFile(modLocation("block/${MNames.ANDROID_CHARGER}_${part.serializedName}")))
						.rotationY(dir.front.yRotationBlockstateNorth())
						.addModel()
						.condition(AndroidChargerBlock.PART, part)
						.condition(BlockRotationFreedom.ONE.property, dir)
						.end()
				}
			}
		}

		with(provider.getMultipartBuilder(MBlocks.MATTER_BOTTLER)) {
			for (dir in BlockRotationFreedom.ONE.possibleValues) {
				for (enum in WorkerState.SEMI_WORKER_STATE.possibleValues) {
					part().modelFile(provider.models().getExistingFile(modLocation("matter_bottler_${enum.name.lowercase()}")))
						.rotationY(dir.front.yRotationBlockstateNorth())
						.addModel()
						.condition(BlockRotationFreedom.ONE.property, dir)
						.condition(WorkerState.WORKER_STATE, enum)
						.end()
				}
			}

			for (dir in BlockRotationFreedom.ONE.possibleValues) {
				for (enum in MatterBottlerBlock.SLOT_PROPERTIES) {
					part().modelFile(provider.models().getExistingFile(modLocation("matter_bottler_${enum.name}_open")))
						.rotationY(dir.front.yRotationBlockstateNorth())
						.addModel()
						.condition(BlockRotationFreedom.ONE.property, dir)
						.condition(enum, false)
						.end()

					part().modelFile(provider.models().getExistingFile(modLocation("matter_bottler_${enum.name}_closed")))
						.rotationY(dir.front.yRotationBlockstateNorth())
						.addModel()
						.condition(BlockRotationFreedom.ONE.property, dir)
						.condition(enum, true)
						.end()
				}
			}
		}
	}

	provider.block(MBlocks.MATTER_DECOMPOSER)
	provider.block(MBlocks.MATTER_REPLICATOR)
	provider.block(MBlocks.PLATE_PRESS)
	provider.block(MBlocks.TWIN_PLATE_PRESS)
	provider.block(MBlocks.GRAVITATION_STABILIZER)
	provider.block(MBlocks.GRAVITATION_STABILIZER_LENS)
	provider.block(MBlocks.POWERED_BLAST_FURNACE)
	provider.block(MBlocks.POWERED_FURNACE)

	provider.block(MBlocks.STORAGE_POWER_SUPPLIER)
	provider.block(MBlocks.MATTER_RECYCLER)
	provider.block(MBlocks.MATTER_RECONSTRUCTOR)
	provider.block(MBlocks.ENERGY_SERVO)
	provider.block(MBlocks.COBBLESTONE_GENERATOR)
	provider.block(MBlocks.ESSENCE_STORAGE)

	provider.exec {
		for (crate in MRegistry.CARGO_CRATES.allBlocks.values) {
			provider.getVariantBuilder(crate).forAllStates {
				return@forAllStates arrayOf(
					ConfiguredModel.builder()
						.modelFile(provider.models().getExistingFile(
							modLocation("${crate.registryName!!.path}_${if (it.getValue(
										CargoCrateBlock.IS_OPEN)) "open" else "closed"}")
						))
						.rotationY(it.getValue(BlockRotationFreedom.ONE.property).front.yRotationBlockstateNorth())
						.buildLast()
				)
			}
		}

		with(provider.getMultipartBuilder(MBlocks.STORAGE_BUS)) {
			for (dir in BlockRotationFreedom.TWO.possibleValues) {
				part().modelFile(provider.models().getExistingFile(modLocation("storage_bus")))
					.rotationX(dir.front.xRotationBlockstateNorth())
					.rotationY(dir.front.yRotationBlockstateNorth())
					.addModel()
					.condition(BlockRotationFreedom.TWO.property, dir)
					.end()

				part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_connection")))
					.rotationX(dir.front.xRotationBlockstateSouth())
					.rotationY(dir.front.yRotationBlockstateSouth())
					.addModel()
					.condition(CableBlock.MAPPING_CONNECTION_PROP[dir.front]!!, true)
					.end()
			}

			part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_core")))
				.addModel().end()
		}

		with(provider.getMultipartBuilder(MBlocks.STORAGE_IMPORTER)) {
			for (dir in BlockRotationFreedom.TWO.possibleValues) {
				part().modelFile(provider.models().getExistingFile(modLocation("storage_importer")))
					.rotationX(dir.front.xRotationBlockstateNorth())
					.rotationY(dir.front.yRotationBlockstateNorth())
					.addModel()
					.condition(BlockRotationFreedom.TWO.property, dir)
					.end()

				part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_connection")))
					.rotationX(dir.front.xRotationBlockstateSouth())
					.rotationY(dir.front.yRotationBlockstateSouth())
					.addModel()
					.condition(CableBlock.MAPPING_CONNECTION_PROP[dir.front]!!, true)
					.end()
			}

			part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_core")))
				.addModel().end()
		}

		with(provider.getMultipartBuilder(MBlocks.STORAGE_EXPORTER)) {
			for (dir in BlockRotationFreedom.TWO.possibleValues) {
				part().modelFile(provider.models().getExistingFile(modLocation("storage_exporter")))
					.rotationX(dir.front.xRotationBlockstateNorth())
					.rotationY(dir.front.yRotationBlockstateNorth())
					.addModel()
					.condition(BlockRotationFreedom.TWO.property, dir)
					.end()

				part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_connection")))
					.rotationX(dir.front.xRotationBlockstateSouth())
					.rotationY(dir.front.yRotationBlockstateSouth())
					.addModel()
					.condition(CableBlock.MAPPING_CONNECTION_PROP[dir.front]!!, true)
					.end()
			}

			part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_core")))
				.addModel().end()
		}
	}
}
