-- FoldableTrigger.lua (LS25 - korrigierte Version)
FoldableTrigger = {
    MOD_NAME = g_currentModName,
    SPEC_NAME = g_currentModName .. ".foldableTrigger",
    prerequisitesPresent = function (specializations)
        return SpecializationUtil.hasSpecialization(Foldable, specializations)
    end,
    initSpecialization = function ()
        local schema = Vehicle.xmlSchema
        schema:setXMLSpecializationType("FoldableTrigger")
        schema:register(XMLValueType.NODE_INDEX, "vehicle.foldableTrigger#triggerNode", "Player trigger node")
        schema:setXMLSpecializationType()
    end
}

function FoldableTrigger.registerFunctions(vehicleType)
    SpecializationUtil.registerFunction(vehicleType, "onFoldableTriggerCallback", FoldableTrigger.onFoldableTriggerCallback)
end

function FoldableTrigger.registerEventListeners(vehicleType)
    SpecializationUtil.registerEventListener(vehicleType, "onLoad", FoldableTrigger)
    SpecializationUtil.registerEventListener(vehicleType, "onLoadFinished", FoldableTrigger)
    SpecializationUtil.registerEventListener(vehicleType, "onDelete", FoldableTrigger)
    SpecializationUtil.registerEventListener(vehicleType, "onFoldStateChanged", FoldableTrigger)
end

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

    spec.triggerNode = self.xmlFile:getValue("vehicle.foldableTrigger#triggerNode", nil, self.components, self.i3dMappings)

    if spec.triggerNode ~= nil then
        -- use the classic addTrigger (addPlayerTrigger kann nicht verfügbar sein und wirft nil error)
        addTrigger(spec.triggerNode, "onFoldableTriggerCallback", self)
    end

    spec.isPlayerInRange = false
end

function FoldableTrigger:onLoadFinished(savegame)
    local spec = self.spec_foldableTrigger
    spec.activatable = FoldableTriggerActivatable.new(self)
end

function FoldableTrigger:onDelete()
    local spec = self.spec_foldableTrigger

    if spec.triggerNode ~= nil then
        removeTrigger(spec.triggerNode)
    end

    if spec.activatable ~= nil then
        g_currentMission.activatableObjectsSystem:removeActivatable(spec.activatable)
    end
end

function FoldableTrigger:onFoldStateChanged(direction, moveToMiddle)
    local spec = self.spec_foldableTrigger
    if spec.activatable ~= nil then
        spec.activatable:updateText()
    end
end

-- robustere Player-Erkennung im Trigger-Callback
function FoldableTrigger:onFoldableTriggerCallback(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId)
    local spec = self.spec_foldableTrigger
    if spec == nil then
        return
    end

    local function isPlayerNode(node)
        -- single player shortcut
        if g_currentMission.player ~= nil and node == g_currentMission.player.rootNode then
            return true
        end

        -- multiplayer / multiple players: prüfe bekannte player-Tabellenfelder
        if g_currentMission.players ~= nil then
            for _, player in pairs(g_currentMission.players) do
                if player ~= nil then
                    if player.rootNode == node or player.node == node or player.characterNode == node then
                        return true
                    end
                end
            end
        end

        return false
    end

    if isPlayerNode(otherId) then
        if onEnter then
            spec.isPlayerInRange = true
            if spec.activatable ~= nil then
                spec.activatable:updateText()
                g_currentMission.activatableObjectsSystem:addActivatable(spec.activatable)
            end
        elseif onLeave then
            spec.isPlayerInRange = false
            if spec.activatable ~= nil then
                g_currentMission.activatableObjectsSystem:removeActivatable(spec.activatable)
            end
        end
    end
end

-- Activatable-Klasse (unverändert / nur kleinste Robustheits-Checks)
FoldableTriggerActivatable = {}
local FoldableTriggerActivatable_mt = Class(FoldableTriggerActivatable)

function FoldableTriggerActivatable.new(vehicle)
    local self = setmetatable({}, FoldableTriggerActivatable_mt)
    self.vehicle = vehicle
    self:updateText()
    return self
end

function FoldableTriggerActivatable:getIsActivatable()
    if not g_currentMission.accessHandler:canPlayerAccess(self.vehicle) then
        return false
    end
    return self.vehicle.spec_foldableTrigger.isPlayerInRange
end

function FoldableTriggerActivatable:run()
    local spec = self.vehicle.spec_foldable
    local toggleDirection = self.vehicle:getToggledFoldDirection()
    local allowed, warning = self.vehicle:getIsFoldAllowed(toggleDirection, false)

    if allowed then
        if toggleDirection == spec.turnOnFoldDirection then
            self.vehicle:setFoldState(toggleDirection, true)
        else
            self.vehicle:setFoldState(toggleDirection, false)
        end
    elseif warning ~= nil then
        g_currentMission:showBlinkingWarning(warning, 2000)
    end
end

function FoldableTriggerActivatable:getDistance(x, y, z)
    if self.vehicle.spec_foldableTrigger.triggerNode ~= nil then
        local tx, ty, tz = getWorldTranslation(self.vehicle.spec_foldableTrigger.triggerNode)
        return MathUtil.vector3Length(x - tx, y - ty, z - tz)
    end
    return math.huge
end

function FoldableTriggerActivatable:updateText()
    local spec = self.vehicle.spec_foldable
    local direction = self.vehicle:getToggledFoldDirection()

    if direction == spec.turnOnFoldDirection then
        self.activateText = spec.negDirectionText or g_i18n:getText("action_fold")
    else
        self.activateText = spec.posDirectionText or g_i18n:getText("action_unfold")
    end
end
