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

import net.minecraft.core.BlockPos
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.MenuProvider
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.minecraft.world.phys.AABB
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.block.entity.WorkerState
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.capability.moveEnergy
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.menu.tech.AndroidStationMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities

class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
	MatteryPoweredBlockEntity(MBlockEntities.ANDROID_STATION, p_155229_, p_155230_), MenuProvider {

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

	override val energy: ProfiledEnergyStorage<WorkerEnergyStorage> = ProfiledEnergyStorage(object : WorkerEnergyStorage(::markDirtyFast, MachinesConfig.AndroidStation.VALUES) {
		override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
			return super.extractEnergy(howMuch, simulate).also {
				if (!simulate && this.batteryLevel.isZero) {
					if (blockState.getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.IDLE) {
						level?.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS)
					}
				}
			}
		}

		override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
			return super.receiveEnergy(howMuch, simulate).also {
				if (!simulate && it.isPositive) {
					if (blockState.getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.WORKING) {
						level?.setBlock(blockPos, blockState.setValue(
							WorkerState.SEMI_WORKER_STATE,
							WorkerState.WORKING
						), Block.UPDATE_CLIENTS)
					}
				}
			}
		}
	})

	val energyConfig = ConfigurableEnergy(energy)

	init {
		savetables.stateful(::energy, ENERGY_KEY)
	}

	private var tickedOnce = false

	override fun tick() {
		super.tick()

		if (!tickedOnce) {
			tickedOnce = true

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

		if (redstoneControl.isBlockedByRedstone) return
		val level = level ?: return
		val x = blockPos.x.toDouble()
		val y = blockPos.y.toDouble()
		val z = blockPos.z.toDouble()

		for (ent in level.getEntitiesOfClass(ServerPlayer::class.java, AABB(x, y, z, x + 1.0, y + 2.0, z + 1.0))) {
			ent.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresentK {
				if (it.isAndroid)
					moveEnergy(energy, it.androidEnergy, amount = energy.batteryLevel, simulate = false, ignoreFlowRestrictions = true)
			}
		}
	}
}
