rSemiTruck = rSemiTruck or {}
rSemiTruck.TireRestore = rSemiTruck.TireRestore or {}

local TireRestore = rSemiTruck.TireRestore

TireRestore.MOD_DATA_KEY = "w900PatchMissingTiresRestored"

local function getVehicleChosenParts(vehicle)
    if not vehicle or not vehicle.getChoosenParts then
        return nil
    end

    return vehicle:getChoosenParts()
end

local function callLuaFunction(functionName, arg1, arg2, arg3, arg4)
    if not functionName or functionName == "" then
        return nil
    end

    if functionName:find(".", 1, true) then
        local current = _G
        local parts = functionName:split("\\.")
        for index = 1, #parts - 1 do
            if not current then
                return nil
            end
            current = current[parts[index]]
        end
        local func = current and current[parts[#parts]] or nil
        if func then
            return func(arg1, arg2, arg3, arg4)
        end
        return nil
    end

    local func = _G[functionName]
    if func then
        return func(arg1, arg2, arg3, arg4)
    end
    return nil
end

local function isTirePart(part)
    if not part or not part.getId then
        return false
    end

    local partId = part:getId() or ""
    if not string.match(partId, "^Tire") then
        return false
    end

    local itemTypes = part:getItemType()
    return itemTypes ~= nil and not itemTypes:isEmpty()
end

local function createPartInventoryItem(part)
    if not part then
        return nil
    end

    local itemTypes = part:getItemType()
    if not itemTypes or itemTypes:isEmpty() then
        return nil
    end

    if part:getInventoryItem() then
        return part:getInventoryItem()
    end

    local vehicle = part:getVehicle()
    if not vehicle then
        return nil
    end

    local chosenKey = ""
    for index = 1, itemTypes:size() do
        chosenKey = chosenKey .. itemTypes:get(index - 1) .. ";"
    end

    local chosenParts = getVehicleChosenParts(vehicle)
    local itemType = chosenParts and chosenParts:get(chosenKey) or nil
    if not itemType then
        for index = 0, itemTypes:size() - 1 do
            if ZombRand(100) > (100 - (100 / itemTypes:size())) or index == itemTypes:size() - 1 then
                itemType = itemTypes:get(index)
                itemType = itemType:gsub("Base.OldBrake", "Base.NormalBrake")
                if chosenParts then
                    chosenParts:put(chosenKey, itemType)
                end
                break
            end
        end
    end

    if not itemType then
        return nil
    end

    local item = instanceItem(itemType)
    if not item then
        return nil
    end

    local conditionMultiply = 100 / item:getConditionMax()
    if part:getContainerCapacity() and part:getContainerCapacity() > 0 then
        item:setMaxCapacity(part:getContainerCapacity())
    end
    item:setConditionMax(item:getConditionMax() * conditionMultiply)
    item:setConditionNoSound(item:getCondition() * conditionMultiply)
    part:setRandomCondition(item)
    part:setInventoryItem(item)
    return part:getInventoryItem()
end

function TireRestore.getMissingTireParts(vehicle)
    local missingParts = {}
    if not vehicle or not vehicle.getScript then
        return missingParts
    end

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

    for index = 0, script:getPartCount() - 1 do
        local part = vehicle:getPartByIndex(index)
        if isTirePart(part) and not part:getInventoryItem() then
            missingParts[#missingParts + 1] = part
        end
    end

    return missingParts
end

function TireRestore.canRestore(vehicle)
    if not vehicle then
        return false
    end

    local modData = vehicle:getModData()
    if modData and modData[TireRestore.MOD_DATA_KEY] then
        return false
    end

    return #TireRestore.getMissingTireParts(vehicle) > 0
end

function TireRestore.restoreMissingTires(vehicle, playerObj)
    if not TireRestore.canRestore(vehicle) then
        return 0
    end

    local restoredCount = 0
    local missingParts = TireRestore.getMissingTireParts(vehicle)
    for _, part in ipairs(missingParts) do
        local item = createPartInventoryItem(part)
        if item then
            local capacity = part:getContainerCapacity()
            if capacity and capacity > 0 and part.setContainerContentAmount then
                part:setContainerContentAmount(capacity, false, true)
                if item.setItemCapacity then
                    item:setItemCapacity(capacity)
                end
            end

            local initFunction = part:getLuaFunction("init")
            if initFunction then
                callLuaFunction(initFunction, vehicle, part, playerObj)
            end

            restoredCount = restoredCount + 1

            if vehicle.transmitPartItem then
                vehicle:transmitPartItem(part)
            end
            if vehicle.transmitPartModData then
                vehicle:transmitPartModData(part)
            end
            if vehicle.transmitPartCondition then
                vehicle:transmitPartCondition(part)
            end
        end
    end

    if restoredCount > 0 then
        vehicle:getModData()[TireRestore.MOD_DATA_KEY] = true
        if vehicle.transmitModData then
            vehicle:transmitModData()
        end
    end

    return restoredCount
end