local M = {}
M.type = "auxiliary"

local headlighttimer = 0
local ignitiontimer = 0
local ignitiontimer2 = 0
local ignitionchimesnd, doorchimesnd
local chimeNode = nil
local ignitionchimesample, doorajarchimesample
local chimepit = 1.0
local chimevol = 1.0

local function clamp(val, minVal, maxVal)
    if val < minVal then return minVal end
    if val > maxVal then return maxVal end
    return val
end

local function updateGFX(dt)
    local vals = electrics.values
    local doorAjar = (vals.doorFLCoupler_notAttached or 0) > 0 or
                     (vals.doorRLCoupler_notAttached or 0) > 0 or
                     (vals.doorFRCoupler_notAttached or 0) > 0 or
                     (vals.doorRRCoupler_notAttached or 0) > 0

    local headlightsOn = (vals.lowhighbeam or 0) > 0
    local engineOn = (vals.engineRunning or 0) > 0
    local handbrakeOn = (vals.parkingbrake or 0) > 0
    local throttleOn = (vals.throttle_input or 0) > 0.5
    local isArcadeGearbox = (vals.gearboxMode == "arcade")
    local inDriveGear = vals.gear and (vals.gear ~= "N" and vals.gear ~= "P")

    -- Decrement timers safely
    headlighttimer = math.max(0, headlighttimer - dt)
    ignitiontimer = math.max(0, ignitiontimer - dt)

    -- Door chime condition
    if (doorAjar and headlightsOn and not engineOn) or
       (doorAjar and vals.ignitionLevel and vals.ignitionLevel > 0 and vals.ignitionLevel < 2) or
       (handbrakeOn and throttleOn and engineOn and inDriveGear and not isArcadeGearbox) then

        headlighttimer = 0.23

        if not doorchimesnd then
            doorchimesnd = obj:createSFXSource2(doorajarchimesample, "AudioClosest3D", "doorchimesnd", chimeNode, 0)
        end
        obj:setVolumePitch(doorchimesnd, M.chimeSoundDistance() * chimevol / 8, chimepit)
        obj:playSFX(doorchimesnd)
    end

    -- Ignition chime timer logic
    if (vals.ignitionLevel or 0) > 1 then
        if ignitiontimer2 < 5 then
            ignitiontimer2 = ignitiontimer2 + dt
        else
            ignitiontimer2 = 5 -- clamp at max
        end
    else
        ignitiontimer2 = 0
    end

    if vals.ignitionLevel == 2 and ignitiontimer2 < 5 then
        ignitiontimer = 1
        if not ignitionchimesnd then
            ignitionchimesnd = obj:createSFXSource2(ignitionchimesample, "AudioClosest3D", "ignitionchimesnd", chimeNode, 0)
        end
        obj:setVolumePitch(ignitionchimesnd, M.chimeSoundDistance() * chimevol / 8, chimepit)
        obj:playSFX(ignitionchimesnd)
    end
end

local function init(jbeamData)
    ignitionchimesample = jbeamData.gm_b_body_1991_chimesample_ignitionchime
    doorajarchimesample = jbeamData.gm_b_body_1991_chimesample_doorajarchime

    chimevol = jbeamData.chime_vol or 1.0
    chimepit = jbeamData.chime_pitch or 1.0

    headlighttimer = 0
    ignitiontimer = 0
    ignitiontimer2 = 0

    -- Find node only once
    chimeNode = 0
    for k, n in pairs(v.data.nodes) do
        if n.name == "dsh1" then
            chimeNode = k
            break
        end
    end
end

local function chimeSoundDistance()
    local cameraPosition = obj:getCameraPosition()
    local driverNode = beamstate.nodeNameMap['driver'] or 0
    local nodePositions = obj:getPosition() + obj:getNodePosition(driverNode)

    if cameraPosition and nodePositions then
        return math.min(1, 0.0625 / cameraPosition:distance(nodePositions))
    end
    return 1 -- fallback volume
end

local function updateTuning()
    local tuning = v.data.tuning or {}
    chimevol = clamp(tuning.chime_vol or 1.0, 0.0, 1.0)
    chimepit = clamp(tuning.chime_pitch or 1.0, 0.975, 1.1)
end

M.init = init
M.chimeSoundDistance = chimeSoundDistance
M.updateTuning = updateTuning
M.updateGFX = updateGFX

return M
