package ru.dbotthepony.kstarbound.network.packets

import it.unimi.dsi.fastutil.bytes.ByteArrayList
import it.unimi.dsi.fastutil.io.FastByteArrayInputStream
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kommons.io.readByteArray
import ru.dbotthepony.kommons.io.readSignedVarInt
import ru.dbotthepony.kommons.io.writeByteArray
import ru.dbotthepony.kommons.io.writeSignedVarInt
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.client.ClientConnection
import ru.dbotthepony.kstarbound.defs.EntityType
import ru.dbotthepony.kstarbound.network.IClientPacket
import ru.dbotthepony.kstarbound.network.IServerPacket
import ru.dbotthepony.kstarbound.server.ServerConnection
import ru.dbotthepony.kstarbound.world.entities.player.PlayerEntity
import java.io.DataInputStream
import java.io.DataOutputStream
import java.io.File

class EntityCreatePacket(val entityType: EntityType, val storeData: ByteArrayList, val firstNetState: ByteArrayList, val entityID: Int) : IServerPacket, IClientPacket {
	constructor(stream: DataInputStream, isLegacy: Boolean) : this(
		EntityType.entries[stream.readUnsignedByte()],
		ByteArrayList.wrap(stream.readByteArray()),
		ByteArrayList.wrap(stream.readByteArray()),
		stream.readSignedVarInt()
	)

	override fun write(stream: DataOutputStream, isLegacy: Boolean) {
		stream.writeByte(entityType.ordinal)
		stream.writeByteArray(storeData.elements(), 0, storeData.size)
		stream.writeByteArray(firstNetState.elements(), 0, firstNetState.size)
		stream.writeSignedVarInt(entityID)
	}

	override fun play(connection: ServerConnection) {
		if (entityID !in connection.entityIDRange) {
			LOGGER.error("Player $connection tried to create entity $entityType with ID $entityID, but that's outside of allowed range ${connection.entityIDRange}!")
			connection.disconnect("Creating entity with ID $entityID outside of allowed range ${connection.entityIDRange}")
		} else {
			val entity = when (entityType) {
				EntityType.PLAYER -> PlayerEntity(DataInputStream(FastByteArrayInputStream(storeData.elements(), 0, storeData.size)), connection.isLegacy)
				else -> null
			}

			entity ?: return
			entity.networkGroup.read(firstNetState, isLegacy = true)
			entity.entityID = entityID
			entity.isRemote = true
			entity.networkGroup.upstream.enableInterpolation(0.0)

			connection.enqueue {
				entity.joinWorld(this)
			}
		}
	}

	override fun play(connection: ClientConnection) {
		TODO("Not yet implemented")
	}

	companion object {
		private val LOGGER = LogManager.getLogger()
	}
}
