-- Gemeinsame Hilfen für Masseregelung (mit Rundung der Zielmasse)

if not MSW_MassUtil then MSW_MassUtil = {} end

function MSW_MassUtil.isPayloadDampingEnabled()
    local getActivatedModsFn = rawget(_G, "getActivatedMods")
    local activatedMods = getActivatedModsFn and getActivatedModsFn() or nil
    return not (activatedMods and activatedMods:contains("RealisticCarPhysics"))
end

-- Optional: Fahrzeug-Filter (Whitelist/Blacklist/All)
pcall(function() require "MSW_VehicleFilter" end)

local function isTargetVehicle(vehicle)
    if MSW_MassUtil.isPayloadDampingEnabled and not MSW_MassUtil.isPayloadDampingEnabled() then
        return false
    end
    if not vehicle or vehicle:isRemovedFromWorld() then return false end
    if not vehicle.getScript then return false end
    if not MSW_VehicleFilter then return true end
    local mode = tostring(MSW_VehicleFilter.Mode or "whitelist"):lower()
    local sc = vehicle:getScript()
    if not sc then return false end

    local listed = false
    if MSW_VehicleFilter.matchesScript then
        listed = MSW_VehicleFilter.matchesScript(sc)
    elseif MSW_VehicleFilter.isListed then
        listed = MSW_VehicleFilter.isListed(sc:getName())
    end

    if mode == "all" then return true end
    if mode == "blacklist" then return not listed end
    return listed -- whitelist default
end

local function getMassCap(vehicle)
    if not vehicle or not vehicle.getScript or not MSW_VehicleFilter or not MSW_VehicleFilter.getMaxMassCap then
        return nil
    end

    local script = vehicle:getScript()
    if not script then return nil end

    local cap = MSW_VehicleFilter.getMaxMassCap(script:getName())
    if cap and cap > 0 then
        return cap
    end

    cap = MSW_VehicleFilter.getMaxMassCap(script.getFullName and script:getFullName() or nil)
    if cap and cap > 0 then
        return cap
    end

    return nil
end

-- Hole Script-Masse, wenn verfügbar
local function getScriptMass(vehicle)
    local sc = vehicle and vehicle.getScript and vehicle:getScript() or nil
    if not sc then return nil end
    local ok, m = pcall(function() return sc:getMass() end)
    if ok and m and m > 0 then return m end
    return nil
end

-- Summe aller Container-Inhalte (Gewicht)
local function sumContainerWeights(vehicle)
    local total = 0
    local sc = vehicle:getScript()
    local count = sc and sc:getPartCount() or 0
    for i = 0, count - 1 do
        local part = vehicle:getPartByIndex(i)
        if part and part.getItemContainer then
            local c = part:getItemContainer()
            if c then
                total = total + (c:getContentsWeight() or 0)
            end
        end
    end
    return total
end

-- Summe installierter Teile (ohne Container)
local function sumInstalledNonContainerPartsWeight(vehicle)
    local total = 0
    local sc = vehicle:getScript()
    local count = sc and sc:getPartCount() or 0
    for i = 0, count - 1 do
        local part = vehicle:getPartByIndex(i)
        if part and part.getInventoryItem then
            local it = part:getInventoryItem()
            if it then
                local hasCont = (it.getContainer and it:getContainer()) and true or false
                if not hasCont then
                    local w = (it.getActualWeight and it:getActualWeight()) or (it.getWeight and it:getWeight()) or 0
                    total = total + (w or 0)
                end
            end
        end
    end
    return total
end

-- Effektive Nutzlast
function MSW_MassUtil.computePayload(vehicle)
    if not vehicle then return 0,0,0 end
    local cargo = sumContainerWeights(vehicle)
    local parts = sumInstalledNonContainerPartsWeight(vehicle)
    local total = cargo + parts
    return cargo, parts, total
end

-- Basis-Masse bestimmen und cachen
function MSW_MassUtil.getBaseMass(vehicle)
    local md = vehicle:getModData()
    md.msw = md.msw or {}

    if md.msw.massBase0 and md.msw.massBase0 > 0 then
        return md.msw.massBase0
    end
    local mScript = getScriptMass(vehicle)
    if mScript and mScript > 0 then
        md.msw.massBase0 = mScript
        return mScript
    end
    local okCur, cur = pcall(function() return vehicle:getMass() end)
    local _, _, payload = MSW_MassUtil.computePayload(vehicle)
    local base = (okCur and cur) and (cur - payload) or cur or 0
    if base < 100 then base = 500 end
    md.msw.massBase0 = base
    return base
end

-- Wunsch-Masse berechnen (inkl. Rundung auf ganze Zahl)
function MSW_MassUtil.desiredMass(vehicle, factor)
    local base = MSW_MassUtil.getBaseMass(vehicle)
    local _, _, payload = MSW_MassUtil.computePayload(vehicle)
    local desired = base + math.max(0, payload) * math.max(0, math.min(1, factor or 0.55))
    local massCap = getMassCap(vehicle)
    if massCap and desired > massCap then
        desired = massCap
    end
    -- Runde auf volle Zahl
    desired = math.floor(desired + 0.5)
    return desired
end

function MSW_MassUtil.isTargetVehicle(vehicle) return isTargetVehicle(vehicle) end