----------------------------------------------------------------
-- REA_implementResistance.lua
-- Erweiterter realistischer Arbeitswiderstand für REAPlus (LS25)
--
-- Berücksichtigt:
--  - Arbeitstiefe
--  - Arbeitsbreite
--  - Bodenfeuchte & Bodenart
--  - Hangneigung
--  - Front-/Heckgeräte
--  - Reifenprofil (Grip)
--  - Realistische Arbeitsgeschwindigkeit
--
-- ADDITIV – verändert keine bestehende Logik
----------------------------------------------------------------

do
    ------------------------------------------------------------
    -- HILFSFUNKTIONEN
    ------------------------------------------------------------

    local function clamp(v, min, max)
        if v < min then return min end
        if v > max then return max end
        return v
    end

    ------------------------------------------------------------
    -- HANGNEIGUNG
    ------------------------------------------------------------
    local function getSlopeFactor(vehicle)
        if vehicle.rootNode == nil then return 1 end

        local x, y, z = getWorldTranslation(vehicle.rootNode)
        local nx, ny, nz = getTerrainNormalAtWorldPos(
            g_currentMission.terrainRootNode, x, y, z
        )

        local slope = clamp(1 - ny, 0, 0.4)
        return 1 + slope * 2.5
    end

    ------------------------------------------------------------
    -- BODENFEUCHTE + BODENART
    ------------------------------------------------------------
    local function getSoilFactor(vehicle)
        local moisture = vehicle.reaSoilMoisture or 0.2
        local soilType = vehicle.reaSoilType or "loam"

        local moistureFactor = 1 + moisture * 1.2

        local soilFactor = 1
        if soilType == "sand" then
            soilFactor = 0.85
        elseif soilType == "loam" then
            soilFactor = 1.0
        elseif soilType == "clay" then
            soilFactor = 1.25
        end

        return moistureFactor * soilFactor
    end

    ------------------------------------------------------------
    -- REIFENPROFIL (GRIP)
    ------------------------------------------------------------
    local function getTireGripFactor(vehicle)
        local grip = 1.0

        -- Virtual tire pressure from EnhancedVehicle (EV) / other mods
        -- Expected range ~0.8 .. 2.2 (bar-like). Lower pressure -> more field grip, higher -> less.
        local pSpec = vehicle.spec_reaPlusVirtualPressure
        if pSpec ~= nil and pSpec.tpFront ~= nil and pSpec.tpRear ~= nil then
            local p = (pSpec.tpFront + pSpec.tpRear) * 0.5
            -- map 0.8 -> 1.10, 2.2 -> 0.90
            local pf = 1.10 + (p - 0.8) * (-0.2 / 1.4)
            grip = grip * clamp(pf, 0.85, 1.15)
        end

        if vehicle.spec_wheels ~= nil then
            for _, wheel in ipairs(vehicle.spec_wheels.wheels) do
                if wheel.tireType ~= nil then
                    local t = wheel.tireType.name or ""

                    if string.find(t, "mud") or string.find(t, "offroad") then
                        grip = grip * 0.85
                    elseif string.find(t, "street") then
                        grip = grip * 1.15
                    end
                end
            end
        end

        return clamp(grip, 0.75, 1.25)
    end

    ------------------------------------------------------------
    -- GERÄTEINFO
    ------------------------------------------------------------
    local function getImplementInfo(vehicle)
        local depth = 0
        local width = 0
        local isFront = false
        local maxWorkSpeed = nil

        if vehicle.spec_plow ~= nil and vehicle:getIsTurnedOn() then
            depth = 0.30
            width = vehicle.spec_plow.workWidth or 3.0
            maxWorkSpeed = 8
        end

        if vehicle.spec_cultivator ~= nil and vehicle:getIsTurnedOn() then
            depth = 0.15
            width = vehicle.spec_cultivator.workWidth or 4.0
            maxWorkSpeed = 12
        end

        if vehicle.spec_sowingMachine ~= nil and vehicle:getIsTurnedOn() then
            depth = 0.06
            width = vehicle.spec_sowingMachine.workWidth or 6.0
            maxWorkSpeed = 15
        end

        if vehicle.spec_attachable ~= nil
            and vehicle.spec_attachable.attacherJoint ~= nil then
            isFront =
                vehicle.spec_attachable.attacherJoint.jointType
                == AttacherJoints.JOINTTYPE_FRONT
        end

        return depth, width, isFront, maxWorkSpeed
    end

    ------------------------------------------------------------
    -- UPDATE-HOOK
    ------------------------------------------------------------
    local oldUpdate = Vehicle.update

    Vehicle.update = function(self, dt)
        oldUpdate(self, dt)

        if self == nil then return end
        if self.spec_motorized == nil then return end
        if not (self.getIsTurnedOn and self:getIsTurnedOn()) then return end

        local depth, width, isFront, maxWorkSpeed =
            getImplementInfo(self)

        if depth <= 0 or width <= 0 then return end

        --------------------------------------------------------
        -- WIDERSTANDSFAKTOREN
        --------------------------------------------------------
        local depthFactor = clamp(depth / 0.35, 0, 1)
        local widthFactor = clamp(width / 8.0, 0.5, 1.6)
        local slopeFactor = getSlopeFactor(self)
        local soilFactor  = getSoilFactor(self)
        local tireFactor  = getTireGripFactor(self)

        local positionFactor = isFront and 0.65 or 1.0

        local resistance =
            1
            + depthFactor * 0.6
            + (widthFactor - 1) * 0.7

        resistance =
            resistance
            * slopeFactor
            * soilFactor
            * positionFactor
            * tireFactor

        --------------------------------------------------------
        -- MOTORLAST / LEISTUNG
        --------------------------------------------------------
        local spec = self.spec_motorized
        if spec.motor ~= nil then
            spec.reaOrigTorque =
                spec.reaOrigTorque or spec.motor.torqueScale or 1

            spec.motor.torqueScale =
                spec.reaOrigTorque / resistance
        end

        --------------------------------------------------------
        -- REALISTISCHE ARBEITSGESCHWINDIGKEIT
        --------------------------------------------------------
        if maxWorkSpeed ~= nil then
            local speed = self:getLastSpeed() or 0
            local maxMS = maxWorkSpeed / 3.6

            if speed > maxMS then
                self.reaSlipIndex = math.max(
                    self.reaSlipIndex or 0,
                    (speed - maxMS) * 0.4
                )
            end
        end

        --------------------------------------------------------
        -- ZUSÄTZLICHER SCHLUPF (Sound + Gefühl)
        --------------------------------------------------------
        self.reaSlipIndex = math.max(
            self.reaSlipIndex or 0,
            depthFactor * widthFactor * 0.3
        )
    end
end
