package ru.dbotthepony.kstarbound.world.api

import ru.dbotthepony.kstarbound.Registries
import ru.dbotthepony.kstarbound.Registry
import ru.dbotthepony.kstarbound.defs.tile.BuiltinMetaMaterials
import ru.dbotthepony.kstarbound.defs.tile.TileModifierDefinition
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
import java.io.DataInputStream

data class MutableTileState(
	override var material: Registry.Entry<TileDefinition> = BuiltinMetaMaterials.NULL,
	override var modifier: Registry.Entry<TileModifierDefinition> = BuiltinMetaMaterials.EMPTY_MOD,
	override var color: TileColor = TileColor.DEFAULT,
	override var hueShift: Float = 0f,
	override var modifierHueShift: Float = 0f,
) : AbstractTileState() {
	override fun immutable(): ImmutableTileState {
		return POOL.intern(ImmutableTileState(material, modifier, color, hueShift, modifierHueShift))
	}

	override fun mutable(): MutableTileState {
		return this
	}

	fun empty() {
		emptyTile()
		emptyModifier()
	}

	fun emptyTile() {
		material = BuiltinMetaMaterials.EMPTY
		color = TileColor.DEFAULT
		hueShift = 0f
	}

	fun emptyModifier() {
		modifier = BuiltinMetaMaterials.EMPTY_MOD
		modifierHueShift = 0f
	}

	fun setHueShift(value: Int): MutableTileState {
		if (value < 0) {
			hueShift = 0f
		} else if (value >= 255) {
			hueShift = 360f
		} else {
			hueShift = value / 255f * 360f
		}

		return this
	}

	fun setModHueShift(value: Int): MutableTileState {
		if (value < 0) {
			modifierHueShift = 0f
		} else if (value >= 255) {
			modifierHueShift = 360f
		} else {
			modifierHueShift = value / 255f * 360f
		}

		return this
	}

	fun read(stream: DataInputStream): MutableTileState {
		material = Registries.tiles[stream.readUnsignedShort()] ?: BuiltinMetaMaterials.EMPTY
		setHueShift(stream.readUnsignedByte())
		color = TileColor.of(stream.readUnsignedByte())
		modifier = Registries.tileModifiers[stream.readUnsignedShort()] ?: BuiltinMetaMaterials.EMPTY_MOD
		setModHueShift(stream.readUnsignedByte())
		return this
	}
}
