package ru.dbotthepony.mc.otm.block.entity.storage

import net.minecraft.core.BlockPos
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.graph.storage.StorageNode
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.menu.storage.DriveRackMenu
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
import ru.dbotthepony.mc.otm.storage.optics.priority
import ru.dbotthepony.mc.otm.storage.optics.powered
import ru.dbotthepony.mc.otm.storage.optics.flow
import java.util.function.Consumer

class DriveRackBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.DRIVE_RACK, blockPos, blockState) {
	override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::markDirtyFast, MachinesConfig.DRIVE_RACK))
	val cell = StorageNode(energy)
	val energyConfig = ConfigurableEnergy(energy)

	var insertPriority = 0
		set(value) {
			field = value
			markDirtyFast()
		}

	var extractPriority = 0
		set(value) {
			field = value
			markDirtyFast()
		}

	var mode = FlowDirection.BI_DIRECTIONAL
		set(value) {
			field = value
			markDirtyFast()
		}

	val container: MatteryContainer = object : MatteryContainer(::markDirtyFast, 4) {
		override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
			super.setChanged(slot, new, old)

			old.getCapability(MatteryCapability.CONDENSATION_DRIVE)?.let {
				cell.removeStorageComponent(it.priority(::insertPriority, ::extractPriority).powered(energy).flow(::mode))
			}

			new.getCapability(MatteryCapability.CONDENSATION_DRIVE)?.let {
				cell.addStorageComponent(it.priority(::insertPriority, ::extractPriority).powered(energy).flow(::mode))
			}
		}
	}.also(::addDroppableContainer)

	init {
		savetables.stateful(::energy, ENERGY_KEY)
		savetables.stateful(::container, INVENTORY_KEY)
		exposeGlobally(MatteryCapability.STORAGE_NODE, cell)
		savetablesConfig.int(::insertPriority)
		savetablesConfig.int(::extractPriority)
		savetablesConfig.enum(::mode, map = FlowDirection::valueOf)

		redstoneControl.addListener(Consumer {
			cell.isDetached = it
		})
	}

	override fun setLevel(level: Level) {
		super.setLevel(level)
		cell.discover(this)
	}

	override fun tick() {
		super.tick()
		cell.tickEnergyDemanding()
	}

	override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
		return DriveRackMenu(containerID, inventory, this)
	}

	override fun setRemoved() {
		super.setRemoved()
		cell.isValid = false
	}
}
