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

import net.minecraft.core.BlockPos
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.chat.Component
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.Level
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.mc.otm.block.entity.IRedstoneControlled
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.block.entity.SynchronizedRedstoneControl
import ru.dbotthepony.mc.otm.menu.decorative.HoloSignMenu
import ru.dbotthepony.mc.otm.once
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MBlocks

class HoloSignBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryBlockEntity(MBlockEntities.HOLO_SIGN, blockPos, blockState), MenuProvider, IRedstoneControlled {
	override val redstoneControl = SynchronizedRedstoneControl(synchronizer) { _, _ -> setChanged() }

	var signText by synchronizer.string("", setter = { value, access, remote ->
		setChanged()
		access.write(value)
	})

	var isLocked = false

	init {
		savetables.string(::signText)
		savetablesLevel.bool(::isLocked)
		savetables.stateful(::redstoneControl)
	}

	override fun createMenu(p_39954_: Int, p_39955_: Inventory, p_39956_: Player): AbstractContainerMenu {
		return HoloSignMenu(p_39954_, p_39955_, this)
	}

	override fun getDisplayName(): Component {
		return MBlocks.HOLO_SIGN.name
	}

	override fun setLevel(level: Level) {
		super.setLevel(level)

		level.once {
			if (!isRemoved && this.level == level) {
				redstoneControl.redstoneSignal = level.getBestNeighborSignal(blockPos)
			}
		}
	}

	override fun load(nbt: CompoundTag) {
		super.load(nbt)

		if (!isLocked)
			signText = truncate(signText)
	}

	companion object {
		const val DEFAULT_MAX_NEWLINES = 8
		const val DEFAULT_MAX_LINE_LENGTH = 15
		private val NEWLINES = Regex("\r?\n")

		fun truncate(input: String): String {
			val lines = input.split(NEWLINES)
			val result = ArrayList<String>(lines.size.coerceAtMost(DEFAULT_MAX_NEWLINES))

			for (i in 0 until lines.size.coerceAtMost(DEFAULT_MAX_NEWLINES)) {
				if (lines[i].length > DEFAULT_MAX_LINE_LENGTH) {
					result.add(lines[i].substring(0, DEFAULT_MAX_LINE_LENGTH))
				} else {
					result.add(lines[i])
				}
			}

			return result.joinToString("\n")
		}
	}
}
