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

import net.minecraft.core.BlockPos
import net.minecraft.world.item.context.BlockPlaceContext
import net.minecraft.world.level.BlockGetter
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.EntityBlock
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.entity.BlockEntityTicker
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.block.state.StateDefinition
import net.minecraft.world.phys.shapes.BooleanOp
import net.minecraft.world.phys.shapes.CollisionContext
import net.minecraft.world.phys.shapes.Shapes
import net.minecraft.world.phys.shapes.VoxelShape
import ru.dbotthepony.mc.otm.block.CableBlock
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.storage.StorageExporterBlockEntity
import ru.dbotthepony.mc.otm.block.entity.storage.StorageImporterBlockEntity
import ru.dbotthepony.mc.otm.core.get
import ru.dbotthepony.mc.otm.core.math.BlockRotation
import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
import ru.dbotthepony.mc.otm.shapes.BlockShapes
import ru.dbotthepony.mc.otm.core.math.unaryMinus

class StorageImporterBlock : RotatableMatteryBlock(DEFAULT_MACHINE_PROPERTIES), EntityBlock {
	init {
		tooltips.blockEntityEnergy()
	}

	override fun rotationFreedom(): BlockRotationFreedom {
		return BlockRotationFreedom.DIRECTIONAL
	}

	override fun newBlockEntity(p_153215_: BlockPos, p_153216_: BlockState): BlockEntity {
		return StorageImporterBlockEntity(p_153215_, p_153216_)
	}

	init {
		registerDefaultState(defaultBlockState()
			.setValue(CableBlock.CONNECTION_SOUTH, false)
			.setValue(CableBlock.CONNECTION_WEST, false)
			.setValue(CableBlock.CONNECTION_EAST, false)
			.setValue(CableBlock.CONNECTION_NORTH, false)
			.setValue(CableBlock.CONNECTION_UP, false)
			.setValue(CableBlock.CONNECTION_DOWN, false))
	}

	override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
		super.createBlockStateDefinition(builder)

		builder.add(
			CableBlock.CONNECTION_SOUTH,
			CableBlock.CONNECTION_WEST,
			CableBlock.CONNECTION_EAST,
			CableBlock.CONNECTION_NORTH,
			CableBlock.CONNECTION_UP,
			CableBlock.CONNECTION_DOWN
		)
	}

	override fun <T : BlockEntity?> getTicker(
		p_153212_: Level,
		p_153213_: BlockState,
		p_153214_: BlockEntityType<T>
	): BlockEntityTicker<T>? {
		if (p_153212_.isClientSide || p_153214_ !== MBlockEntities.STORAGE_IMPORTER)
			return null

		return BlockEntityTicker { _, _, _, tile -> if (tile is StorageImporterBlockEntity) tile.tick() }
	}

	override fun getStateForPlacement(context: BlockPlaceContext): BlockState? {
		return super.getStateForPlacement(context)?.setValue(BlockRotationFreedom.DIRECTIONAL.property, BlockRotation.of(-context.clickedFace))
	}

	private val shapes = getShapeForEachStateMattery {
		Shapes.joinUnoptimized(CableBlock.getShapeFor(it, 0.185), BlockShapes.STORAGE_IMPORTER.rotateFromNorth(it[rotationProperty]).computeShape(), BooleanOp.OR)
	}

	@Suppress("OVERRIDE_DEPRECATION")
	override fun getShape(
		p_60555_: BlockState,
		p_60556_: BlockGetter,
		p_60557_: BlockPos,
		p_60558_: CollisionContext
	): VoxelShape {
		return shapes[p_60555_]!!
	}
}

class StorageExporterBlock : RotatableMatteryBlock(DEFAULT_MACHINE_PROPERTIES), EntityBlock {
	init {
		tooltips.blockEntityEnergy()
	}

	override fun rotationFreedom(): BlockRotationFreedom {
		return BlockRotationFreedom.DIRECTIONAL
	}

	override fun newBlockEntity(p_153215_: BlockPos, p_153216_: BlockState): BlockEntity {
		return StorageExporterBlockEntity(p_153215_, p_153216_)
	}

	init {
		registerDefaultState(defaultBlockState()
			.setValue(CableBlock.CONNECTION_SOUTH, false)
			.setValue(CableBlock.CONNECTION_WEST, false)
			.setValue(CableBlock.CONNECTION_EAST, false)
			.setValue(CableBlock.CONNECTION_NORTH, false)
			.setValue(CableBlock.CONNECTION_UP, false)
			.setValue(CableBlock.CONNECTION_DOWN, false))
	}

	override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
		super.createBlockStateDefinition(builder)

		builder.add(
			CableBlock.CONNECTION_SOUTH,
			CableBlock.CONNECTION_WEST,
			CableBlock.CONNECTION_EAST,
			CableBlock.CONNECTION_NORTH,
			CableBlock.CONNECTION_UP,
			CableBlock.CONNECTION_DOWN
		)
	}

	override fun <T : BlockEntity?> getTicker(
		p_153212_: Level,
		p_153213_: BlockState,
		p_153214_: BlockEntityType<T>
	): BlockEntityTicker<T>? {
		if (p_153212_.isClientSide || p_153214_ !== MBlockEntities.STORAGE_EXPORTER)
			return null

		return BlockEntityTicker { _, _, _, tile -> if (tile is StorageExporterBlockEntity) tile.tick() }
	}

	override fun getStateForPlacement(context: BlockPlaceContext): BlockState? {
		return super.getStateForPlacement(context)?.setValue(BlockRotationFreedom.DIRECTIONAL.property, BlockRotation.of(-context.clickedFace))
	}

	private val shapes = getShapeForEachStateMattery {
		Shapes.joinUnoptimized(CableBlock.getShapeFor(it, 0.185), BlockShapes.STORAGE_EXPORTER.rotateFromNorth(it[rotationProperty]).computeShape(), BooleanOp.OR)
	}

	@Suppress("OVERRIDE_DEPRECATION")
	override fun getShape(
		p_60555_: BlockState,
		p_60556_: BlockGetter,
		p_60557_: BlockPos,
		p_60558_: CollisionContext
	): VoxelShape {
		return shapes[p_60555_]!!
	}
}
