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

import net.minecraft.core.BlockPos
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
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.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.transferChecked
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.graph.storage.StorageNode
import ru.dbotthepony.mc.otm.graph.storage.StorageGraph
import ru.dbotthepony.mc.otm.menu.storage.StoragePowerSupplierMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities

class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.STORAGE_POWER_SUPPLIER, blockPos, blockState) {
	override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
		return StoragePowerSupplierMenu(containerID, inventory, this)
	}

	val cell = StorageNode()
	val energy = WorkerEnergyStorage(this, MachinesConfig.STORAGE_POWER_SUPPLIER)

	init {
		savetable(::energy, ENERGY_KEY)

		exposeEnergyGlobally(energy)
		exposeGlobally(MatteryCapability.STORAGE_NODE, cell)
	}

	var powerPassed = Decimal.ZERO
		private set

	init {
		savetables.decimal(::powerPassed, POWER_PASSED_KEY)
	}

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

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

	override fun tick() {
		super.tick()

		if (redstoneControl.isBlockedByRedstone)
			return

		if (energy.batteryLevel.isZero)
			return

		if (cell.graph.powerDemandingNodes.isEmpty())
			return

		var demand = Decimal.ZERO
		var i = 0

		val available = energy.batteryLevel.coerceAtMost(MachinesConfig.STORAGE_POWER_SUPPLIER.throughput)

		for (demanding in cell.graph.powerDemandingNodes) {
			val received = demanding.receiveEnergy(available, true)

			if (received.isPositive) {
				demand += received
				i++
			}
		}

		if (demand.isZero) {
			return
		} else if (demand < available) {
			for (demanding in cell.graph.powerDemandingNodes) {
				powerPassed += energy.transferChecked(demanding, available, false)
			}
		} else {
			val forEach = available / i

			for (demanding in cell.graph.powerDemandingNodes) {
				powerPassed += energy.transferChecked(demanding, forEach, false)
			}
		}
	}

	companion object {
		const val POWER_PASSED_KEY = "powerPassed"
	}
}
