---@class TerraFarmCabControl
TerraFarmCabControl = {}
local TerraFarmCabControl_mt = Class(TerraFarmCabControl)

------------------------------------------------------------
-- Vereisten / registratie
------------------------------------------------------------

function TerraFarmCabControl.prerequisitesPresent(specializations)
    -- Geen echte vereisten, jij voegt 'm zelf alleen toe op TerraFarm-bakken
    return true
end

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

function TerraFarmCabControl.registerFunctions(vehicleType)
    SpecializationUtil.registerFunction(vehicleType, "tfSetHeightFromBucket", TerraFarmCabControl.tfSetHeightFromBucket)
end

------------------------------------------------------------
-- onLoad
------------------------------------------------------------

function TerraFarmCabControl:onLoad(savegame)
    local spec = {}
    self.spec_tfCabControl = spec

    -- Node van de bak (snijrand)
    spec.bucketNode = self.xmlFile:getValue("vehicle.terraFarmCabControl#bucketNode", nil, self.components, self.i3dMappings)
    -- Optioneel tweede punt om een lijn / helling te maken
    spec.bucketEndNode = self.xmlFile:getValue("vehicle.terraFarmCabControl#bucketEndNode", spec.bucketNode, self.components, self.i3dMappings)

    if spec.bucketNode == nil then
        Logging.warning("TerraFarmCabControl: bucketNode niet gezet voor %s", self.configFileName)
    end
end

------------------------------------------------------------
-- Input events registreren
------------------------------------------------------------

function TerraFarmCabControl:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection)
    if not self.isClient then
        return
    end

    local spec = self.spec_tfCabControl
    if spec == nil or spec.bucketNode == nil then
        return
    end

    -- Eigen actionEvents-tabel voor deze spec
    if spec.actionEvents == nil then
        spec.actionEvents = {}
    end

    -- Oude events opruimen
    self:clearActionEventsTable(spec.actionEvents)

    -- Voor werktuigen kijken we naar isActiveForInputIgnoreSelection
    if not isActiveForInputIgnoreSelection then
        return
    end

    -- Gebruik Werktuigfunctie 3 (IMPLEMENT_EXTRA3)
    local _, actionEventId = self:addActionEvent(
        spec.actionEvents,
        InputAction.IMPLEMENT_EXTRA3,
        self,
        TerraFarmCabControl.action_setHeightFromBucket,
        false,  -- triggerUp
        true,   -- triggerDown
        false,  -- startActive
        true    -- callbackState
    )

    if actionEventId ~= nil and g_i18n ~= nil then
        local text = g_i18n:getText("input_TF_SET_HEIGHT_FROM_BUCKET") or "TerraFarm: hoogte instellen met bak"
        g_inputBinding:setActionEventText(actionEventId, text)
    end
end

function TerraFarmCabControl:action_setHeightFromBucket(actionName, inputValue, callbackState, isAnalog)
    -- Alleen reageren op key-down
    if inputValue == 0 then
        return
    end

    self:tfSetHeightFromBucket()
end

------------------------------------------------------------
-- Hoogte uit bak naar TerraFarm Surveyor sturen
------------------------------------------------------------

function TerraFarmCabControl:tfSetHeightFromBucket()
    local spec = self.spec_tfCabControl
    if spec == nil or spec.bucketNode == nil then
        return
    end

    ----------------------------------------------------------------
    -- 1. Positie(s) op de bak ophalen
    ----------------------------------------------------------------
    local sx, sy, sz = getWorldTranslation(spec.bucketNode)
    local ex, ey, ez

    if spec.bucketEndNode ~= nil and spec.bucketEndNode ~= spec.bucketNode then
        -- Tweede referentiepunt opgegeven in XML
        ex, ey, ez = getWorldTranslation(spec.bucketEndNode)
    else
        -- Klein stukje "vooruit" vanaf de bak, zodat start en end niet exact hetzelfde zijn
        local dx, dy, dz = localDirectionToWorld(spec.bucketNode, 0, 0, 1)
        ex = sx + dx
        ey = sy + dy
        ez = sz + dz
    end

    ----------------------------------------------------------------
    -- 2. Bijbehorende TerraFarm Machine / Surveyor opzoeken
    ----------------------------------------------------------------
    local rootVehicle = self.getRootVehicle and self:getRootVehicle() or self
    local surveyor = nil

    -- Eerst proberen via Machine:getSurveyor()
    if rootVehicle ~= nil and rootVehicle.getSurveyor ~= nil then
        surveyor = rootVehicle:getSurveyor()
    end

    -- Als er geen externe Surveyor is, maar rootVehicle zelf een Surveyor-spec heeft
    if surveyor == nil and rootVehicle ~= nil and rootVehicle.spec_surveyor ~= nil then
        surveyor = rootVehicle

        if rootVehicle.setSurveyorId ~= nil and rootVehicle.getSurveyorId ~= nil then
            local id = surveyor:getSurveyorId()
            if id ~= nil then
                rootVehicle:setSurveyorId(id)
            end
        end
    end

    ----------------------------------------------------------------
    -- 3. TerraFarm calibreren of foutmelding geven
    ----------------------------------------------------------------
    if surveyor ~= nil and surveyor.setCalibration ~= nil then
        surveyor:setCalibration(sx, sy, sz, ex, ey, ez)

        if g_currentMission ~= nil then
            local msg = g_i18n:getText("tf_message_heightSetFromBucket") or "TerraFarm hoogte ingesteld vanaf bak"
            g_currentMission:showBlinkingWarning(msg, 3000)
        end
    else
        if g_currentMission ~= nil then
            g_currentMission:showBlinkingWarning("Geen TerraFarm surveyor gevonden of toegewezen", 4000)
        end

        Logging.warning(
            "TerraFarmCabControl: geen Surveyor gevonden (rootVehicle: %s)",
            rootVehicle and rootVehicle.configFileName or "nil"
        )
    end
end
