package ru.dbotthepony.kstarbound.world.api

import com.github.benmanes.caffeine.cache.Interner
import ru.dbotthepony.kstarbound.Registry
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.defs.tile.LiquidDefinition
import ru.dbotthepony.kstarbound.network.LegacyNetworkLiquidState
import java.io.DataInputStream
import java.io.DataOutputStream

sealed class AbstractLiquidState {
	abstract val state: Registry.Entry<LiquidDefinition>
	abstract val level: Float
	abstract val pressure: Float
	abstract val isInfinite: Boolean

	abstract fun mutable(): MutableLiquidState
	abstract fun immutable(): ImmutableLiquidState

	fun toLegacyNet(): LegacyNetworkLiquidState {
		if (state.id != null && state.id!! in 1 .. 255) {
			return LegacyNetworkLiquidState(state.id!!, (level * 255f).toInt().coerceIn(0, 255))
		} else {
			return LegacyNetworkLiquidState.EMPTY
		}
	}

	fun write(stream: DataOutputStream) {
		stream.writeByte(state.id ?: 0)
		stream.writeFloat(level)
		stream.writeFloat(pressure)
		stream.writeBoolean(isInfinite)
	}

	companion object {
		fun skip(stream: DataInputStream) {
			stream.skipNBytes(1 + 4 + 4 + 1)
		}

		@JvmStatic
		protected val POOL: Interner<ImmutableLiquidState> = if (Starbound.DEDUP_CELL_STATES) Starbound.interner() else Interner { it }

		val EMPTY: ImmutableLiquidState = POOL.intern(ImmutableLiquidState())
	}
}
