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

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.level.block.Block
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.ForgeHooks
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.capability.*
import ru.dbotthepony.mc.otm.capability.energy.GeneratorEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.HandlerFilter
import ru.dbotthepony.mc.otm.menu.tech.ChemicalGeneratorMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.core.math.Decimal

class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.CHEMICAL_GENERATOR, pos, state) {
	override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
		return ChemicalGeneratorMenu(containerID, inventory, this)
	}

	val batteryContainer = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer)
	val residueContainer = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer)
	val fuelContainer = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer)

	val batteryItemHandler = batteryContainer.handler(HandlerFilter.Chargeable)
	val residueItemHandler = residueContainer.handler(HandlerFilter.OnlyOut)
	val fuelItemHandler = fuelContainer.handler(HandlerFilter.ChemicalFuel)

	val energy = ProfiledEnergyStorage(GeneratorEnergyStorage(::markDirtyFast, MachinesConfig.ChemicalGenerator.VALUES::energyCapacity, MachinesConfig.ChemicalGenerator.VALUES::energyThroughput))

	val itemConfig = ConfigurableItemHandler(
		input = fuelItemHandler,
		output = residueItemHandler,
		battery = batteryItemHandler,
		backDefault = ItemHandlerMode.BATTERY)

	val energyConfig = ConfigurableEnergy(energy)

	init {
		for (piece in energyConfig.pieces.values)
			piece.automatePush = true

		savetables.stateful(::energy, ENERGY_KEY)
		savetables.stateful(::batteryContainer)
		savetables.stateful(::residueContainer)
		savetables.stateful(::fuelContainer)

		savetables.int(::workTicks)
		savetables.int(::workTicksTotal)
	}

	override fun markDirtyFast() {
		super.markDirtyFast()
		checkFuelSlot = true
	}

	var workTicks = 0
		private set

	var workTicksTotal = 0
		private set

	private var checkFuelSlot = true

	override fun tick() {
		super.tick()

		if (workTicks > 0) {
			workTicks--
			energy.receiveEnergy(MachinesConfig.ChemicalGenerator.VALUES.energyConsumption, false)

			if (workTicks == 0) {
				workTicksTotal = 0
				checkFuelSlot = true
			}

			if (blockState.getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.WORKING) {
				level?.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING), Block.UPDATE_CLIENTS)
			}
		} else if (blockState.getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.IDLE) {
			level?.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS)
		}

		if (workTicks == 0 && !redstoneControl.isBlockedByRedstone && checkFuelSlot) {
			if (!fuelContainer[0].isEmpty) {
				val ticks = ForgeHooks.getBurnTime(fuelContainer[0], null) / MachinesConfig.ChemicalGenerator.RATIO

				if (
					ticks > 0 &&
					(energy.batteryLevel <= Decimal.ONE || MachinesConfig.ChemicalGenerator.VALUES.energyConsumption * ticks + energy.batteryLevel <= energy.maxBatteryLevel) &&
					residueContainer.fullyAddItem(fuelContainer[0].item.getCraftingRemainingItem(fuelContainer[0].copyWithCount(1)))
				) {
					workTicksTotal = ticks
					workTicks = workTicksTotal
					fuelContainer.removeItem(0, 1)
				}
			}

			checkFuelSlot = false
		}

		if (energy.batteryLevel.isPositive) {
			for (item in batteryContainer) {
				item.energy?.also {
					moveEnergy(energy, it, MachinesConfig.ChemicalGenerator.VALUES.energyThroughput, simulate = false)
				}
			}
		}
	}
}
