package ru.dbotthepony.mc.otm.block.decorative

import net.minecraft.ChatFormatting
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.server.level.ServerLevel
import net.minecraft.sounds.SoundEvent
import net.minecraft.sounds.SoundEvents
import net.minecraft.sounds.SoundSource
import net.minecraft.util.RandomSource
import net.minecraft.util.StringRepresentable
import net.minecraft.world.InteractionResult
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.DyeColor
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.SoundType
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.block.state.StateDefinition
import net.minecraft.world.level.block.state.properties.BlockStateProperties
import net.minecraft.world.level.block.state.properties.EnumProperty
import net.minecraft.world.level.gameevent.GameEvent
import net.minecraft.world.level.material.MapColor
import net.minecraft.world.phys.BlockHitResult
import net.minecraft.world.phys.shapes.CollisionContext
import net.minecraft.world.phys.shapes.VoxelShape
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.getShapeForEachState
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.get
import ru.dbotthepony.mc.otm.core.math.plus
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.item.tool.RedstoneInteractorItem
import ru.dbotthepony.mc.otm.shapes.BlockShapes

class ComputerTerminalBlock(val color: DyeColor?) : RotatableMatteryBlock(
	Properties.of()
		.mapColor(color?.mapColor ?: MapColor.COLOR_LIGHT_BLUE)
		.sound(SoundType.METAL)
		.explosionResistance(15f)
		.destroyTime(1.5f)
) {
	private val shapes = getShapeForEachState(rotationProperty) { BlockShapes.COMPUTER_TERMINAL.rotateFromNorth(it[rotationProperty]).computeShape() }

	init {
		registerDefaultState(defaultBlockState().set(BlockStateProperties.POWERED, false).set(TICKS, RedstoneInteractorItem.TickTimer.TICK_20))
	}

	override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
		super.createBlockStateDefinition(builder)
		builder.add(BlockStateProperties.POWERED)
		builder.add(TICKS)
	}

	override fun getSignal(p_60483_: BlockState, p_60484_: BlockGetter, p_60485_: BlockPos, p_60486_: Direction): Int {
		return if (p_60483_[BlockStateProperties.POWERED]) 15 else 0
	}

	override fun getDirectSignal(
		p_60559_: BlockState,
		p_60560_: BlockGetter,
		p_60561_: BlockPos,
		p_60562_: Direction
	): Int {
		// weird that p_60559_[rotationProperty].front should be used and not p_60559_[rotationProperty].back
		// minecraft engine shenanigans
		return if (p_60559_[BlockStateProperties.POWERED] && p_60559_[rotationProperty].front == p_60562_) 15 else 0
	}

	override fun isSignalSource(p_60571_: BlockState): Boolean {
		return true
	}

	private fun updateNeighbours(blockState: BlockState, blockPos: BlockPos, level: Level) {
		level.updateNeighborsAt(blockPos, this)
		level.updateNeighborsAt(blockPos + blockState[rotationProperty].back, this)
	}

	override fun useWithoutItem(
		blockState: BlockState,
		level: Level,
		blockPos: BlockPos,
		ply: Player,
		blockHitResult: BlockHitResult
	): InteractionResult {
		if (ply.isShiftKeyDown) {
			val current = blockState[TICKS]
			val next = RedstoneInteractorItem.TickTimer.entries.getOrElse(current.ordinal + 1) { RedstoneInteractorItem.TickTimer.TICK_2 }

			level.playSound(ply, blockPos, SoundEvents.DISPENSER_FAIL, SoundSource.BLOCKS, 0.3f, 1.1f)
			level.gameEvent(ply, GameEvent.BLOCK_ACTIVATE, blockPos)

			if (!level.isClientSide) {
				ply.sendSystemMessage(TranslatableComponent("otm.gui.tick_timer_set", next.ticks.toString()))
				level.setBlock(blockPos, blockState.set(TICKS, next), UPDATE_ALL)
			}

			return InteractionResult.sidedSuccess(level.isClientSide)
		}

		if (blockState[BlockStateProperties.POWERED]) {
			return InteractionResult.CONSUME
		} else {
			if (!level.isClientSide) {
				level.setBlock(blockPos, blockState.set(BlockStateProperties.POWERED, true), UPDATE_ALL)
				updateNeighbours(blockState, blockPos, level)
				level.scheduleTick(blockPos, this, blockState[TICKS].ticks)
			}

			level.playSound(ply, blockPos, SoundEvents.STONE_BUTTON_CLICK_ON, SoundSource.BLOCKS, 1f, 1f)
			level.gameEvent(ply, GameEvent.BLOCK_ACTIVATE, blockPos)
			return InteractionResult.sidedSuccess(level.isClientSide)
		}
	}

	override fun tick(blockState: BlockState, level: ServerLevel, blockPos: BlockPos, random: RandomSource) {
		super.tick(blockState, level, blockPos, random)

		if (blockState[BlockStateProperties.POWERED]) {
			level.setBlock(blockPos, blockState.set(BlockStateProperties.POWERED, false), UPDATE_ALL)
			level.playSound(null, blockPos, SoundEvents.STONE_BUTTON_CLICK_OFF, SoundSource.BLOCKS, 1f, 1f)
			level.gameEvent(null, GameEvent.BLOCK_DEACTIVATE, blockPos)
			updateNeighbours(blockState, blockPos, level)
		}
	}

	init {
		tooltips.add(TranslatableComponent("otm.decorative").withStyle(ChatFormatting.GRAY))
		tooltips.add(TranslatableComponent("otm.computer_terminal_tooltip").withStyle(ChatFormatting.GRAY))
		tooltips.add(TranslatableComponent("otm.computer_terminal_tooltip1").withStyle(ChatFormatting.GRAY))
		tooltips.painted(color)
	}

	override fun getShape(
		state: BlockState,
		blockGetter: BlockGetter,
		pos: BlockPos,
		context: CollisionContext
	): VoxelShape {
		return shapes[state]!!
	}

	companion object {
		val TICKS: EnumProperty<RedstoneInteractorItem.TickTimer> = EnumProperty.create("ticks", RedstoneInteractorItem.TickTimer::class.java)
	}
}
