local modFilename, isMod, isDlc, dlcsDirectoryIndex = Utils.removeModDirectory(g_currentModDirectory)


-- Only apply this fix, if it is not already fixed by a patch
if not _G["g_supportAnimationFixHolmerEnabled"] then
    _G["g_supportAnimationFixHolmerEnabled"] = true

    -- check temporary variable to block support animation on post attach in delayedOnAttach is set to false
    local oldGetIsSupportAnimationAllowed = Attachable.getIsSupportAnimationAllowed
    Attachable.getIsSupportAnimationAllowed = function(self, supportAnimation)
        if not self.supportAnimationFixHolmerBlock or supportAnimation.delayedOnAttach then
            return oldGetIsSupportAnimationAllowed(self, supportAnimation)
        end

        return false
    end

    -- add temporary blocking variable while post attach -> see above
    local oldPostAttach = Attachable.postAttach
    Attachable.postAttach = function(self, attacherVehicle, inputJointDescIndex, jointDescIndex)
        self.supportAnimationFixHolmerBlock = true
        oldPostAttach(self, attacherVehicle, inputJointDescIndex, jointDescIndex)
        self.supportAnimationFixHolmerBlock = nil
    end

    -- play non delayed support animations on pre attach
    local oldPreAttach = Attachable.preAttach
    Attachable.preAttach = function(self, attacherVehicle, inputJointDescIndex, jointDescIndex)
        oldPreAttach(self, attacherVehicle, inputJointDescIndex, jointDescIndex)
        local spec = self.spec_attachable
        for _, supportAnimation in ipairs(spec.supportAnimations) do
            if self:getIsSupportAnimationAllowed(supportAnimation) then
                if not supportAnimation.delayedOnAttach then
                    self:playAnimation(supportAnimation.animationName, -1, nil, true)
                    if self.propertyState == Vehicle.PROPERTY_STATE_SHOP_CONFIG then
                        AnimatedVehicle.updateAnimationByName(self, supportAnimation.animationName, 9999999)
                    end
                end
            end
        end
    end

    -- load setting from xml
    local oldLoadSupportAnimationFromXML = Attachable.loadSupportAnimationFromXML
    Attachable.loadSupportAnimationFromXML = function(self, supportAnimation, xmlFile, key)
        supportAnimation.delayedOnAttach = Utils.getNoNil(getXMLBool(xmlFile, key.."#delayedOnAttach"), true) -- defines if the animation is played before or after the attaching process

        return oldLoadSupportAnimationFromXML(self, supportAnimation, xmlFile, key)
    end

    -- update support animations directly after attaching if the attachment is loaded from xml
    local oldLoadAttachmentsFromXMLFile = AttacherJoints.loadAttachmentsFromXMLFile
    AttacherJoints.loadAttachmentsFromXMLFile = function(self, xmlFile, key, idsToVehicle)
        oldLoadAttachmentsFromXMLFile(self, xmlFile, key, idsToVehicle)

        local i = 0
        while true do
            local attachmentKey = string.format("%s.attachment(%d)", key, i)
            if not hasXMLProperty(xmlFile, attachmentKey) then
                break
            end

            local attachmentId = getXMLString(xmlFile, attachmentKey.."#attachmentId")
            if attachmentId ~= nil then
                local attachment = idsToVehicle[attachmentId]
                if attachment ~= nil then
                    local attacherVehicle = attachment:getAttacherVehicle()
                    if attacherVehicle ~= nil and attacherVehicle == self then
                        local implement = attacherVehicle:getImplementByObject(attachment)
                        implement.loadFromSavegame = true
                    end

                    local attachableSpec = attachment.spec_attachable
                    for _, supportAnimation in ipairs(attachableSpec.supportAnimations) do
                        AnimatedVehicle.updateAnimationByName(attachment, supportAnimation.animationName, 9999999)
                    end
                end
            end

            i = i + 1
        end
    end

    -- update support animations directly after attaching if the attachment is loaded from xml (this time after smooth attached, which is normally skipped, was played)
    local oldPostAttachImplement = AttacherJoints.postAttachImplement
    AttacherJoints.postAttachImplement = function(self, implement)
        oldPostAttachImplement(self, implement)

        if implement.loadFromSavegame then
            if implement.object ~= nil then
                local attachableSpec = implement.object.spec_attachable
                for _, supportAnimation in ipairs(attachableSpec.supportAnimations) do
                    AnimatedVehicle.updateAnimationByName(implement.object, supportAnimation.animationName, 9999999)
                end
            end
        end
    end

    -- fix for sync of rotation based limit
    Cylindered.updateRotationBasedLimits = function(self, tool, dependentTool)
       if dependentTool.rotationBasedLimits ~= nil  then
            local state = Cylindered.getMovingToolState(self, tool)
            if dependentTool.rotationBasedLimits ~= nil then
                local minRot, maxRot, minTrans, maxTrans = dependentTool.rotationBasedLimits:get(state)

                if minRot ~= nil then
                    dependentTool.movingTool.rotMin = minRot
                end
                if maxRot ~= nil then
                    dependentTool.movingTool.rotMax = maxRot
                end
                if minTrans ~= nil then
                    dependentTool.movingTool.transMin = minTrans
                end
                if maxTrans ~= nil then
                    dependentTool.movingTool.transMax = maxTrans
                end

                local isDirty = false
                if minRot ~= nil or maxRot ~= nil then
                    isDirty = isDirty or Cylindered.setToolRotation(self, dependentTool.movingTool, 0, 0)
                end
                if minTrans ~= nil or maxTrans ~= nil then
                    isDirty = isDirty or Cylindered.setToolTranslation(self, dependentTool.movingTool, 0, 0)
                end

                if isDirty then
                    Cylindered.setDirty(self, dependentTool.movingTool)

                    -- sync the new limited rotation values and also the new rotation limits
                    self:raiseDirtyFlags(dependentTool.movingTool.dirtyFlag)
                    self:raiseDirtyFlags(self.spec_cylindered.cylinderedDirtyFlag)
                end
            end
        end
    end

    -- fix to sync start and end line to client
    Foldable.onAIImplementStartLine = function(self)
        local spec = self.spec_foldable
        if spec.allowUnfoldingByAI and spec.foldMiddleAnimTime ~= nil and spec.foldMiddleAIRaiseDirection ~= 0 then
            self:setFoldState(-spec.foldMiddleAIRaiseDirection, false)
        end
    end

    Foldable.onAIImplementEndLine = function(self)
        local spec = self.spec_foldable
        if spec.allowUnfoldingByAI and spec.foldMiddleAnimTime ~= nil and spec.foldMiddleAIRaiseDirection ~= 0 then
            if spec.foldMiddleAIRaiseDirection > 0 then
                if spec.foldAnimTime < spec.foldMiddleAnimTime then
                    self:setFoldState(1, true)
                end
            else
                if spec.foldAnimTime > spec.foldMiddleAnimTime then
                    self:setFoldState(-1, true)
                end
            end
        end
    end

    -- add forceAllowDetachWhileLifted attribute for input attacher joints to force allow detaching while the tool is lifted
    local oldLoadInputAttacherJoint = Attachable.loadInputAttacherJoint
    Attachable.loadInputAttacherJoint = function(self, xmlFile, key, inputAttacherJoint, index)
        inputAttacherJoint.forceAllowDetachWhileLifted = Utils.getNoNil(getXMLBool(self.xmlFile, key.."#forceAllowDetachWhileLifted"), false)
        return oldLoadInputAttacherJoint(self, xmlFile, key, inputAttacherJoint, index)
    end

    AttacherJoints.isDetachAllowed = function(self, superFunc)
        local detachAllowed, warning, showWarning = superFunc(self)
        if not detachAllowed then
            return detachAllowed, warning, showWarning
        end

        local spec = self.spec_attacherJoints
        for attacherJointIndex, attacherJoint in ipairs(spec.attacherJoints) do
            if not attacherJoint.allowDetachingWhileLifted then
                if not attacherJoint.moveDown then
                    local implement = self:getImplementByJointDescIndex(attacherJointIndex)
                    if implement ~= nil then
                        local inputAttacherJoint = implement.object:getInputAttacherJointByJointDescIndex(implement.inputJointDescIndex)
                        if inputAttacherJoint ~= nil and not inputAttacherJoint.forceAllowDetachWhileLifted then
                            return false, string.format(g_i18n:getText("warning_lowerImplementFirst"), implement.object.typeDesc)
                        end
                    end
                end
            end
        end

        return true
    end
end
