HookLiftTrailerFixedTexts = {
	prerequisitesPresent = function (specializations)
		return SpecializationUtil.hasSpecialization(AnimatedVehicle, specializations) and SpecializationUtil.hasSpecialization(Foldable, specializations)
	end,
	initSpecialization = function ()
		local schema = Vehicle.xmlSchema

		schema:setXMLSpecializationType("HookLiftTrailerFixedTexts")
		schema:register(XMLValueType.FLOAT, "vehicle.hookLiftTrailer.jointLimits.key(?)#time", "Key time")
		schema:register(XMLValueType.VECTOR_ROT, "vehicle.hookLiftTrailer.jointLimits.key(?)#rotLimit", "Rotation limit", "0 0 0")
		schema:register(XMLValueType.VECTOR_TRANS, "vehicle.hookLiftTrailer.jointLimits.key(?)#transLimit", "Translation limit", "0 0 0")
		schema:register(XMLValueType.STRING, "vehicle.hookLiftTrailer.jointLimits#refAnimation", "Reference animation", "unfoldHand")
		schema:register(XMLValueType.STRING, "vehicle.hookLiftTrailer.unloadingAnimation#name", "Unload animation", "unloading")
		schema:register(XMLValueType.FLOAT, "vehicle.hookLiftTrailer.unloadingAnimation#speed", "Unload animation speed", 1)
		schema:register(XMLValueType.FLOAT, "vehicle.hookLiftTrailer.unloadingAnimation#reverseSpeed", "Unload animation reverse speed", -1)
		schema:setXMLSpecializationType()
	end
}

HookLiftTrailerFixedTexts.currentModName = g_currentModName;

local function getL10nText(text)
	if text:sub(1, 6) == "$l10n_" then
		text = g_i18n:getText(text:sub(7), HookLiftTrailerFixedTexts.currentModName);
	elseif g_i18n:hasText(text, HookLiftTrailerFixedTexts.currentModName) then
		text = g_i18n:getText(text, HookLiftTrailerFixedTexts.currentModName);
	end;

	return text;
end;


function HookLiftTrailerFixedTexts.registerFunctions(vehicleType)
	SpecializationUtil.registerFunction(vehicleType, "startTipping", HookLiftTrailerFixedTexts.startTipping)
	SpecializationUtil.registerFunction(vehicleType, "stopTipping", HookLiftTrailerFixedTexts.stopTipping)
	SpecializationUtil.registerFunction(vehicleType, "getIsTippingAllowed", HookLiftTrailerFixedTexts.getIsTippingAllowed)
	SpecializationUtil.registerFunction(vehicleType, "getCanDetachContainer", HookLiftTrailerFixedTexts.getCanDetachContainer)
end

function HookLiftTrailerFixedTexts.registerOverwrittenFunctions(vehicleType)
	SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsFoldAllowed", HookLiftTrailerFixedTexts.getIsFoldAllowed)
	SpecializationUtil.registerOverwrittenFunction(vehicleType, "isDetachAllowed", HookLiftTrailerFixedTexts.isDetachAllowed)
	SpecializationUtil.registerOverwrittenFunction(vehicleType, "getDoConsumePtoPower", HookLiftTrailerFixedTexts.getDoConsumePtoPower)
	SpecializationUtil.registerOverwrittenFunction(vehicleType, "getPtoRpm", HookLiftTrailerFixedTexts.getPtoRpm)
end

function HookLiftTrailerFixedTexts.registerEventListeners(vehicleType)
	SpecializationUtil.registerEventListener(vehicleType, "onLoad", HookLiftTrailerFixedTexts)
	SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", HookLiftTrailerFixedTexts)
	SpecializationUtil.registerEventListener(vehicleType, "onUpdateTick", HookLiftTrailerFixedTexts)
	SpecializationUtil.registerEventListener(vehicleType, "onPostAttachImplement", HookLiftTrailerFixedTexts)
	SpecializationUtil.registerEventListener(vehicleType, "onPreDetachImplement", HookLiftTrailerFixedTexts)
end

function HookLiftTrailerFixedTexts:onLoad(savegame)
	self.spec_hookLiftTrailerFixedTexts = {};
	local spec = self.spec_hookLiftTrailerFixedTexts
	spec.jointLimits = AnimCurve.new(linearInterpolatorN)
	local i = 0

	while true do
		local key = string.format("vehicle.hookLiftTrailer.jointLimits.key(%d)", i)

		if not self.xmlFile:hasProperty(key) then
			if i == 0 then
				spec.jointLimits = nil
			end

			break
		end

		local t = self.xmlFile:getValue(key .. "#time")
		local rx, ry, rz = self.xmlFile:getValue(key .. "#rotLimit", "0 0 0")
		local tx, ty, tz = self.xmlFile:getValue(key .. "#transLimit", "0 0 0")

		spec.jointLimits:addKeyframe({
			rx,
			ry,
			rz,
			tx,
			ty,
			tz,
			time = t
		})

		i = i + 1
	end

	local xmlFile = loadXMLFile("vehicle", self.xmlFile.filename);

	spec.refAnimation = self.xmlFile:getValue("vehicle.hookLiftTrailer.jointLimits#refAnimation", "unfoldHand")
	spec.unloadingAnimation = self.xmlFile:getValue("vehicle.hookLiftTrailer.unloadingAnimation#name", "unloading")
	spec.unloadingAnimationSpeed = self.xmlFile:getValue("vehicle.hookLiftTrailer.unloadingAnimation#speed", 1)
	spec.unloadingAnimationReverseSpeed = self.xmlFile:getValue("vehicle.hookLiftTrailer.unloadingAnimation#reverseSpeed", -1)
	spec.texts = {
		unloadContainer = getL10nText(Utils.getNoNil(getXMLString(xmlFile, "vehicle.hookLiftTrailer.texts#unloadContainer"), "unload_container")),
		loadContainer = getL10nText(Utils.getNoNil(getXMLString(xmlFile, "vehicle.hookLiftTrailer.texts#loadContainer"), "load_container")),
		unloadArm = getL10nText(Utils.getNoNil(getXMLString(xmlFile, "vehicle.hookLiftTrailer.texts#unloadArm"), "unload_arm")),
		loadArm = getL10nText(Utils.getNoNil(getXMLString(xmlFile, "vehicle.hookLiftTrailer.texts#loadArm"), "load_arm"))
	}

	delete(xmlFile);
end

function HookLiftTrailerFixedTexts:onPostLoad(savegame)
	local spec = self.spec_hookLiftTrailerFixedTexts
	local foldableSpec = self.spec_foldable
	foldableSpec.posDirectionText = spec.texts.unloadArm
	foldableSpec.negDirectionText = spec.texts.loadArm
end

function HookLiftTrailerFixedTexts:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
	local spec = self.spec_hookLiftTrailerFixedTexts

	if spec.attachedContainer ~= nil then
		local animTime = self:getAnimationTime(spec.refAnimation)
		spec.attachedContainer.object.allowsDetaching = animTime > 0.95

		if (self:getIsAnimationPlaying(spec.refAnimation) or not spec.attachedContainer.limitLocked) and spec.jointLimits ~= nil and not spec.attachedContainer.implement.attachingIsInProgress then
			local v = spec.jointLimits:get(animTime)

			for i = 1, 3 do
				setJointRotationLimit(spec.attachedContainer.jointIndex, i - 1, true, -v[i], v[i])
				setJointTranslationLimit(spec.attachedContainer.jointIndex, i + 2, true, -v[i + 3], v[i + 3])
			end

			if animTime >= 0.99 then
				spec.attachedContainer.limitLocked = true
			end
		end
	end
end

function HookLiftTrailerFixedTexts:onPostAttachImplement(attachable, inputJointDescIndex, jointDescIndex)
	local spec = self.spec_hookLiftTrailerFixedTexts
	local attacherJoint = attachable:getActiveInputAttacherJoint()

	if attacherJoint ~= nil and attacherJoint.jointType == AttacherJoints.JOINTTYPE_HOOKLIFT then
		local jointDesc = self:getAttacherJointByJointDescIndex(jointDescIndex)
		spec.attachedContainer = {
			jointIndex = jointDesc.jointIndex,
			implement = self:getImplementByObject(attachable),
			object = attachable,
			limitLocked = false
		}
		local foldableSpec = self.spec_foldable
		foldableSpec.posDirectionText = spec.texts.unloadContainer
		foldableSpec.negDirectionText = spec.texts.loadContainer
	end
end

function HookLiftTrailerFixedTexts:onPreDetachImplement(implement)
	local spec = self.spec_hookLiftTrailerFixedTexts

	if spec.attachedContainer ~= nil and implement == spec.attachedContainer.implement then
		local foldableSpec = self.spec_foldable
		foldableSpec.posDirectionText = spec.texts.unloadArm
		foldableSpec.negDirectionText = spec.texts.loadArm
		spec.attachedContainer = nil
	end
end

function HookLiftTrailerFixedTexts:startTipping()
	local spec = self.spec_hookLiftTrailerFixedTexts

	self:playAnimation(spec.unloadingAnimation, spec.unloadingAnimationSpeed, self:getAnimationTime(spec.unloadingAnimation), true)
end

function HookLiftTrailerFixedTexts:stopTipping()
	local spec = self.spec_hookLiftTrailerFixedTexts

	self:playAnimation(spec.unloadingAnimation, spec.unloadingAnimationReverseSpeed, self:getAnimationTime(spec.unloadingAnimation), true)
end

function HookLiftTrailerFixedTexts:getIsTippingAllowed()
	local spec = self.spec_hookLiftTrailerFixedTexts

	return self:getAnimationTime(spec.refAnimation) == 0
end

function HookLiftTrailerFixedTexts:getCanDetachContainer()
	local spec = self.spec_hookLiftTrailerFixedTexts

	return self:getAnimationTime(spec.refAnimation) == 1
end

function HookLiftTrailerFixedTexts:getIsFoldAllowed(superFunc, direction, onAiTurnOn)
	local spec = self.spec_hookLiftTrailerFixedTexts

	if self:getAnimationTime(spec.unloadingAnimation) > 0 then
		return false
	end

	return superFunc(self, direction, onAiTurnOn)
end

function HookLiftTrailerFixedTexts:isDetachAllowed(superFunc)
	if self:getAnimationTime(self.spec_hookLiftTrailerFixedTexts.unloadingAnimation) == 0 then
		return superFunc(self)
	else
		return false, nil
	end
end

function HookLiftTrailerFixedTexts:getDoConsumePtoPower(superFunc)
	local spec = self.spec_hookLiftTrailerFixedTexts
	local doConsume = superFunc(self)

	return doConsume or self:getIsAnimationPlaying(spec.refAnimation) or self:getIsAnimationPlaying(spec.unloadingAnimation)
end

function HookLiftTrailerFixedTexts:getPtoRpm(superFunc)
	local spec = self.spec_hookLiftTrailerFixedTexts
	local rpm = superFunc(self)

	if self:getIsAnimationPlaying(spec.refAnimation) or self:getIsAnimationPlaying(spec.unloadingAnimation) then
		return self.spec_powerConsumer.ptoRpm
	else
		return rpm
	end
end