--- Opt-in target point for yarder setup ropes.
-- Add this specialization to another vehicle/object type and set
-- <yarderRopeTarget node="i3dMappingName" radius="0.35" /> in its XML.
YarderRopeTarget = {}
YarderRopeTarget.MOD_NAME = g_currentModName
YarderRopeTarget.SPEC_NAME = g_currentModName .. ".yarderRopeTarget"

function YarderRopeTarget.prerequisitesPresent(specializations)
	return true
end

function YarderRopeTarget.initSpecialization()
	local schema = Vehicle.xmlSchema

	schema:setXMLSpecializationType("YarderRopeTarget")
	schema:register(XMLValueType.NODE_INDEX, "vehicle.yarderRopeTarget#node", "Node the yarder setup rope can connect to")
	schema:register(XMLValueType.NODE_INDEX, "vehicle.yarderRopeTarget#pushNode", "Node the first yarder push rope can connect to", "#node")
	schema:register(XMLValueType.NODE_INDEX, "vehicle.yarderRopeTarget#pushNode02", "Node the second yarder push rope can connect to", "#pushNode")
	schema:register(XMLValueType.NODE_INDEX, "vehicle.yarderRopeTarget#rotNode", "Node the yarder ropes can rotate around", "#node")
	schema:register(XMLValueType.NODE_INDEX, "vehicle.yarderRopeTarget#pushRotNode", "Node the first yarder push rope can rotate around", "#rotNode")
	schema:register(XMLValueType.NODE_INDEX, "vehicle.yarderRopeTarget#pushRotNode02", "Node the second yarder push rope can rotate around", "#pushRotNode")
	schema:register(XMLValueType.FLOAT, "vehicle.yarderRopeTarget#radius", "Validation radius around the rope target node", 0.35)
	schema:register(XMLValueType.VECTOR_ROT, "vehicle.yarderRopeTarget#hookRotation", "Local rotation for hook visuals on this target", "0 0 0")
	schema:register(XMLValueType.VECTOR_TRANS, "vehicle.yarderRopeTarget#hookTranslation", "Local translation for hook visuals on this target", "0 0 0")
	schema:register(XMLValueType.VECTOR_ROT, "vehicle.yarderRopeTarget#blockRotation", "Local rotation for block hook visuals on this target", "#hookRotation")
	schema:register(XMLValueType.VECTOR_TRANS, "vehicle.yarderRopeTarget#blockTranslation", "Local translation for block hook visuals on this target", "#hookTranslation")
	schema:setXMLSpecializationType()
end

function YarderRopeTarget.registerFunctions(vehicleType)
	SpecializationUtil.registerFunction(vehicleType, "getYarderRopeTargetNode", YarderRopeTarget.getYarderRopeTargetNode)
	SpecializationUtil.registerFunction(vehicleType, "getYarderRopeTargetPushNode", YarderRopeTarget.getYarderRopeTargetPushNode)
	SpecializationUtil.registerFunction(vehicleType, "getYarderRopeTargetPushNode02", YarderRopeTarget.getYarderRopeTargetPushNode02)
	SpecializationUtil.registerFunction(vehicleType, "getYarderRopeTargetRotNode", YarderRopeTarget.getYarderRopeTargetRotNode)
	SpecializationUtil.registerFunction(vehicleType, "getYarderRopeTargetPushRotNode", YarderRopeTarget.getYarderRopeTargetPushRotNode)
	SpecializationUtil.registerFunction(vehicleType, "getYarderRopeTargetPushRotNode02", YarderRopeTarget.getYarderRopeTargetPushRotNode02)
	SpecializationUtil.registerFunction(vehicleType, "getYarderRopeTargetPosition", YarderRopeTarget.getYarderRopeTargetPosition)
	SpecializationUtil.registerFunction(vehicleType, "getYarderRopeTargetRadius", YarderRopeTarget.getYarderRopeTargetRadius)
	SpecializationUtil.registerFunction(vehicleType, "getYarderRopeTargetHookTransform", YarderRopeTarget.getYarderRopeTargetHookTransform)
	SpecializationUtil.registerFunction(vehicleType, "getYarderRopeTargetBlockTransform", YarderRopeTarget.getYarderRopeTargetBlockTransform)
end

function YarderRopeTarget.registerEventListeners(vehicleType)
	SpecializationUtil.registerEventListener(vehicleType, "onLoad", YarderRopeTarget)
end

function YarderRopeTarget:onLoad(savegame)
	self.spec_yarderRopeTarget = self["spec_" .. YarderRopeTarget.SPEC_NAME]
	local spec = self.spec_yarderRopeTarget

	spec.node = self.xmlFile:getValue("vehicle.yarderRopeTarget#node", nil, self.components, self.i3dMappings)
	spec.pushNode = self.xmlFile:getValue("vehicle.yarderRopeTarget#pushNode", spec.node, self.components, self.i3dMappings)
	spec.pushNode02 = self.xmlFile:getValue("vehicle.yarderRopeTarget#pushNode02", spec.pushNode, self.components, self.i3dMappings)
	spec.rotNode = self.xmlFile:getValue("vehicle.yarderRopeTarget#rotNode", spec.node, self.components, self.i3dMappings)
	spec.pushRotNode = self.xmlFile:getValue("vehicle.yarderRopeTarget#pushRotNode", spec.rotNode, self.components, self.i3dMappings)
	spec.pushRotNode02 = self.xmlFile:getValue("vehicle.yarderRopeTarget#pushRotNode02", spec.pushRotNode, self.components, self.i3dMappings)
	spec.radius = self.xmlFile:getValue("vehicle.yarderRopeTarget#radius", 0.35)
	spec.hookTranslation = self.xmlFile:getValue("vehicle.yarderRopeTarget#hookTranslation", {
		0,
		0,
		0
	}, true)
	spec.hookRotation = self.xmlFile:getValue("vehicle.yarderRopeTarget#hookRotation", {
		0,
		0,
		0
	}, true)
	spec.blockTranslation = self.xmlFile:getValue("vehicle.yarderRopeTarget#blockTranslation", spec.hookTranslation, true)
	spec.blockRotation = self.xmlFile:getValue("vehicle.yarderRopeTarget#blockRotation", spec.hookRotation, true)

	if spec.node == nil then
		Logging.xmlWarning(self.xmlFile, "Missing yarderRopeTarget node for '%s'", self.configFileName)
	end
end

function YarderRopeTarget:getYarderRopeTargetNode()
	return self.spec_yarderRopeTarget.node
end

function YarderRopeTarget:getYarderRopeTargetPushNode()
	return self.spec_yarderRopeTarget.pushNode or self.spec_yarderRopeTarget.node
end

function YarderRopeTarget:getYarderRopeTargetPushNode02()
	return self.spec_yarderRopeTarget.pushNode02 or self.spec_yarderRopeTarget.pushNode or self.spec_yarderRopeTarget.node
end

function YarderRopeTarget:getYarderRopeTargetRotNode()
	return self.spec_yarderRopeTarget.rotNode or self.spec_yarderRopeTarget.node
end

function YarderRopeTarget:getYarderRopeTargetPushRotNode()
	return self.spec_yarderRopeTarget.pushRotNode or self.spec_yarderRopeTarget.rotNode or self.spec_yarderRopeTarget.node
end

function YarderRopeTarget:getYarderRopeTargetPushRotNode02()
	return self.spec_yarderRopeTarget.pushRotNode02 or self.spec_yarderRopeTarget.pushRotNode or self.spec_yarderRopeTarget.rotNode or self.spec_yarderRopeTarget.node
end

function YarderRopeTarget:getYarderRopeTargetPosition()
	local node = self:getYarderRopeTargetNode()

	if node ~= nil and entityExists(node) then
		return getWorldTranslation(node)
	end

	return getWorldTranslation(self.rootNode)
end

function YarderRopeTarget:getYarderRopeTargetRadius()
	return self.spec_yarderRopeTarget.radius
end

function YarderRopeTarget:getYarderRopeTargetHookTransform()
	local spec = self.spec_yarderRopeTarget
	local translation = spec.hookTranslation or {
		0,
		0,
		0
	}
	local rotation = spec.hookRotation or {
		0,
		0,
		0
	}

	return translation[1], translation[2], translation[3], rotation[1], rotation[2], rotation[3]
end

function YarderRopeTarget:getYarderRopeTargetBlockTransform()
	local spec = self.spec_yarderRopeTarget
	local translation = spec.blockTranslation or spec.hookTranslation or {
		0,
		0,
		0
	}
	local rotation = spec.blockRotation or spec.hookRotation or {
		0,
		0,
		0
	}

	return translation[1], translation[2], translation[3], rotation[1], rotation[2], rotation[3]
end
