NuhnMassDistributor = {}

-- CONFIGURATION
local WEIGHT_SCALER = 0.45 
local FRONT_BIAS    = 0.5 
local FRONT_INDEX   = 1   
local REAR_INDEX    = 3   

-- 1. LOGIC (Silent Version)
function NuhnMassDistributor.updateNuhnMass(self, force)
    local s = self.spec_nuhnMass
    local specFill = self.spec_fillUnit

    -- Nil Guards: Ensure data exists before touching physics
    if specFill == nil or specFill.fillUnits == nil or specFill.fillUnits[1] == nil then return end
    if s.frontBase == nil or s.rearBase == nil then return end

    local unit = specFill.fillUnits[1]
    local fillLevel = unit.fillLevel
    local fillTypeIndex = unit.fillType

    -- Robust early exit
    if not force then
        if s.lastAppliedLevel == fillLevel and s.lastFillType == fillTypeIndex then 
            return 
        end
    end

    -- Smart Density Cache
    if s.lastFillType ~= fillTypeIndex then
        local fillType = g_fillTypeManager:getFillTypeByIndex(fillTypeIndex)
        s.cachedDensity = (fillType ~= nil and fillType.massPerLiter > 0) and fillType.massPerLiter or 0.001
        s.lastFillType = fillTypeIndex
    end

    -- Math: Scale and Bias
    local totalLiquidMass = (fillLevel * s.cachedDensity) * WEIGHT_SCALER
    local finalFront = math.max(0.1, s.frontBase + (totalLiquidMass * FRONT_BIAS))
    local finalRear  = math.max(0.1, s.rearBase + (totalLiquidMass * (1 - FRONT_BIAS)))

    -- Authoritative Physics (Server only)
    if self.isServer then
        setMass(s.frontNode, finalFront)
        setMass(s.rearNode, finalRear)
    end

    -- Visual Debug Sync (Server & Client for Shift+2)
    self.components[FRONT_INDEX].mass = finalFront
    self.components[REAR_INDEX].mass = finalRear
    
    s.lastAppliedLevel = fillLevel
end

-- 2. REGISTRATION
function NuhnMassDistributor.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(FillUnit, specializations)
end

function NuhnMassDistributor.registerEventListeners(vehicleType)
    SpecializationUtil.registerEventListener(vehicleType, "onLoad", NuhnMassDistributor)
    SpecializationUtil.registerEventListener(vehicleType, "onLoadFinished", NuhnMassDistributor)
    SpecializationUtil.registerEventListener(vehicleType, "onUpdate", NuhnMassDistributor)
    SpecializationUtil.registerEventListener(vehicleType, "onFillUnitFillLevelChanged", NuhnMassDistributor)
    SpecializationUtil.registerEventListener(vehicleType, "onPostAttach", NuhnMassDistributor)
    SpecializationUtil.registerEventListener(vehicleType, "onPostDetach", NuhnMassDistributor)
end

function NuhnMassDistributor.registerFunctions(vehicleType)
    SpecializationUtil.registerFunction(vehicleType, "updateNuhnMass", NuhnMassDistributor.updateNuhnMass)
end

-- 3. EVENTS
function NuhnMassDistributor:onLoad(savegame)
    self.spec_nuhnMass = {
        isValid = false,
        lastFillType = 0,
        lastAppliedLevel = -1,
        frontBase = nil,
        checkTimer = 0,
        forceUpdatesRemaining = 4 
    }
    
    if self.components[FRONT_INDEX] ~= nil and self.components[REAR_INDEX] ~= nil then
        self.spec_nuhnMass.frontNode = self.components[FRONT_INDEX].node
        self.spec_nuhnMass.rearNode = self.components[REAR_INDEX].node
        self.spec_nuhnMass.isValid = true
    end
end

function NuhnMassDistributor:onLoadFinished(savegame)
    if self.spec_nuhnMass.isValid then
        self.spec_nuhnMass.frontBase = getMass(self.spec_nuhnMass.frontNode)
        self.spec_nuhnMass.rearBase = getMass(self.spec_nuhnMass.rearNode)
    end
end

function NuhnMassDistributor:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
    local s = self.spec_nuhnMass
    if not s.isValid or s.frontBase == nil then return end

    s.checkTimer = s.checkTimer + dt
    if s.checkTimer > 500 then
        local force = s.forceUpdatesRemaining > 0
        if force then
            s.forceUpdatesRemaining = s.forceUpdatesRemaining - 1
        end

        NuhnMassDistributor.updateNuhnMass(self, force)
        s.checkTimer = 0
    end
end

function NuhnMassDistributor:onFillUnitFillLevelChanged(fillUnitIndex, fillLevelDelta, fillTypeIndex, toolType, fillPositionIndex, appliedFillLevelDelta, node)
    if fillUnitIndex == 1 and self.spec_nuhnMass.isValid then
        NuhnMassDistributor.updateNuhnMass(self, false)
    end
end

function NuhnMassDistributor:onPostAttach(attacherVehicle, inputJointDescIndex, jointDescIndex)
    if self.spec_nuhnMass.isValid then
        NuhnMassDistributor.updateNuhnMass(self, true)
    end
end

function NuhnMassDistributor:onPostDetach()
    if self.spec_nuhnMass.isValid then
        NuhnMassDistributor.updateNuhnMass(self, true)
    end
end