package ru.dbotthepony.kstarbound.world.entities

import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.math.Interpolator
import ru.dbotthepony.kstarbound.network.syncher.NetworkedElement
import ru.dbotthepony.kstarbound.network.syncher.NetworkedGroup
import ru.dbotthepony.kstarbound.network.syncher.networkedBoolean
import ru.dbotthepony.kstarbound.network.syncher.networkedFixedPoint
import ru.dbotthepony.kstarbound.network.syncher.networkedItem
import ru.dbotthepony.kstarbound.network.syncher.networkedStatefulItem
import java.io.DataInputStream

/**
 * Players and NPCs
 */
abstract class HumanoidActorEntity() : ActorEntity() {
	abstract val aimPosition: Vector2d

	val effects = EffectEmitter(this)

	// it makes no sense to split ToolUser' logic into separate class
	protected val toolsNetworkGroup = NetworkedGroup()

	var primaryHandItem by toolsNetworkGroup.add(networkedStatefulItem())
	var secondaryHandItem by toolsNetworkGroup.add(networkedStatefulItem())
	var primaryFireTimerNetState by toolsNetworkGroup.add(networkedFixedPoint(Starbound.TIMESTEP).also { it.interpolator = ToolFiringInterpolator })
	var secondaryFireTimerNetState by toolsNetworkGroup.add(networkedFixedPoint(Starbound.TIMESTEP).also { it.interpolator = ToolFiringInterpolator })
	var primaryTimeFiringNetState by toolsNetworkGroup.add(networkedFixedPoint(Starbound.TIMESTEP).also { it.interpolator = ToolFiringInterpolator })
	var secondaryTimeFiringNetState by toolsNetworkGroup.add(networkedFixedPoint(Starbound.TIMESTEP).also { it.interpolator = ToolFiringInterpolator })
	var primaryItemActive by toolsNetworkGroup.add(networkedBoolean())
	var secondaryItemActive by toolsNetworkGroup.add(networkedBoolean())

	private object ToolFiringInterpolator : Interpolator {
		override fun interpolate(t: Double, a: Double, b: Double): Double {
			return if (a >= b) b else Interpolator.Linear.interpolate(t, a, b)
		}
	}

	// same as above
	protected val armorNetworkGroup = NetworkedGroup()

	var headItem by armorNetworkGroup.add(networkedItem())
	var chestItem by armorNetworkGroup.add(networkedItem())
	var legsItem by armorNetworkGroup.add(networkedItem())
	var backItem by armorNetworkGroup.add(networkedItem())
	var headCosmeticItem by armorNetworkGroup.add(networkedItem())
	var chestCosmeticItem by armorNetworkGroup.add(networkedItem())
	var legsCosmeticItem by armorNetworkGroup.add(networkedItem())
	var backCosmeticItem by armorNetworkGroup.add(networkedItem())
}
