-- FilltypeExtension
-- Version: 1.0.0.0
-- Author: Tidde

FilltypeExtension = g_FilltypeExtensionStationaryBalerFW or {}
g_FilltypeExtensionStationaryBalerFW = FilltypeExtension

if FilltypeExtension._initialized then return end

FilltypeExtension._initialized = true
FilltypeExtension.debug = fals


FilltypeExtension.originalStationaryFillTypes      = "STRAW DRYGRASS_WINDROW GRASS_WINDROW CHAFF SUGARBEET_CUT FORAGE"
FilltypeExtension.Filltypes                        = "STRAW GRASS_WINDROW DRYGRASS_WINDROW CHAFF SUGARBEET_CUT FORAGE ALFALFA_WINDROW CLOVER_WINDROW"
FilltypeExtension.additiveFilltypes                = "GRASS_WINDROW DRYGRASS_WINDROW CHAFF ALFALFA_WINDROW CLOVER_WINDROW"
FilltypeExtension.additiveFilltypesForageWagon     = "GRASS_WINDROW ALFALFA_WINDROW CLOVER_WINDROW"
FilltypeExtension.additiveFilltypesForageHarvester = "GRASS_WINDROW DRYGRASS_WINDROW CHAFF ALFALFA_WINDROW CLOVER_WINDROW"

FilltypeExtension.requireBaleType = true

FilltypeExtension._origStatUpper = string.upper(FilltypeExtension.originalStationaryFillTypes or "")

local function getFillTypeIndex(name)
    if name ~= nil and name ~= "" then
        return g_fillTypeManager:getFillTypeIndexByName(string.upper(name))
    end
    return nil
end

local function toNameList(value)
    if type(value) == "table" then
        return value
    elseif type(value) == "string" then
        local result = {}
        for token in string.gmatch(value, "%S+") do
            table.insert(result, token)
        end
        return result
    end
    return {}
end

local function hasBaleTypeEligible(fillTypeIndex)
    if not FilltypeExtension.requireBaleType then
        return true
    end
    if g_baleTypeManager and g_baleTypeManager.fillTypeToBaleTypes then
        local list = g_baleTypeManager.fillTypeToBaleTypes[fillTypeIndex]
        return list ~= nil and #list > 0
    end
    return true
end

local function buildFiltered(list, label)
    local names = toNameList(list)
    local validNames, validIndices, missingNames = {}, {}, {}

    for _, name in ipairs(names) do
        local fillTypeIndex = getFillTypeIndex(name)
        if fillTypeIndex ~= nil and hasBaleTypeEligible(fillTypeIndex) then
            local upperName = string.upper(name)
            table.insert(validNames, upperName)
            table.insert(validIndices, fillTypeIndex)
        else
            table.insert(missingNames, tostring(name))
        end
    end

    local resultString = table.concat(validNames, " ")
    
    if FilltypeExtension.debug and #missingNames > 0 then
        local missingMessage = FilltypeExtension.requireBaleType and " / no BaleType" or ""
        Logging.warning("[FilltypeExtension] Ignored %s (not registered%s): %s", label, missingMessage, table.concat(missingNames, ", "))
    end
    
    return resultString, validIndices
end

local function buildFilteredOnce()
    if FilltypeExtension._filteredBuilt then
        return
    end
    FilltypeExtension._filteredBuilt = true

    FilltypeExtension._intakeStr, FilltypeExtension._intakeIdx = buildFiltered(FilltypeExtension.Filltypes, "Stationary-Baler Intake")
    FilltypeExtension._addBalStr, FilltypeExtension._addBalIdx = buildFiltered(FilltypeExtension.additiveFilltypes, "Baler Additives")
    FilltypeExtension._addFWStr, FilltypeExtension._addFWIdx   = buildFiltered(FilltypeExtension.additiveFilltypesForageWagon, "ForageWagon Additives")
    FilltypeExtension._addFHStr, FilltypeExtension._addFHIdx   = buildFiltered(FilltypeExtension.additiveFilltypesForageHarvester, "ForageHarvester Additives")

    if FilltypeExtension._intakeStr == "" then
        FilltypeExtension._intakeStr = FilltypeExtension.originalStationaryFillTypes or ""
        FilltypeExtension._intakeIdx = {}
    end
end

local function hasSpecialization(vehicle, specName)
    local specialization = g_specializationManager:getSpecializationByName(specName)
    return specialization ~= nil and SpecializationUtil.hasSpecialization(specialization, vehicle.specializations)
end

local function onLoadFillUnitFromXML(vehicle, superFunc, xmlFile, key, entry, index)
    local vehicleType = string.upper(xmlFile:getValue("vehicle#type", "") or "")
    if vehicleType == "BALERSTATIONARY" then
        buildFilteredOnce()
        local currentFillTypes = xmlFile:getValue(key .. "#fillTypes")
        if currentFillTypes ~= nil and string.upper(currentFillTypes) == FilltypeExtension._origStatUpper then
            xmlFile:setValue(key .. "#fillTypes", FilltypeExtension._intakeStr)
        end
    end
    return superFunc(vehicle, xmlFile, key, entry, index)
end
FillUnit.loadFillUnitFromXML = Utils.overwrittenFunction(FillUnit.loadFillUnitFromXML, onLoadFillUnitFromXML)

local function onLoadSpecValueFillTypes(xmlFile, superFunc, customEnvironment, baseDir)
    local vehicleType = string.upper(xmlFile:getValue("vehicle#type", "") or "")
    if vehicleType == "BALERSTATIONARY" then
        buildFilteredOnce()
        local rootName = xmlFile:getRootName()
        local configIndex = 0
        
        while true do
            local configurationKey = string.format("%s.fillUnit.fillUnitConfigurations.fillUnitConfiguration(%d)", rootName, configIndex)
            if not xmlFile:hasProperty(configurationKey) then break end
            
            local unitIndex = 0
            while true do
                local fillUnitKey = string.format("%s.fillUnits.fillUnit(%d)", configurationKey, unitIndex)
                if not xmlFile:hasProperty(fillUnitKey) then break end
                
                local showInShop = xmlFile:getValue(fillUnitKey .. "#showInShop")
                local capacity = xmlFile:getValue(fillUnitKey .. "#capacity")
                
                if (showInShop == nil or showInShop) and (capacity == nil or capacity > 0) then
                    local currentFillTypes = xmlFile:getValue(fillUnitKey .. "#fillTypes")
                    if currentFillTypes ~= nil and string.upper(currentFillTypes) == FilltypeExtension._origStatUpper then
                        xmlFile:setValue(fillUnitKey .. "#fillTypes", FilltypeExtension._intakeStr)
                    end
                end
                unitIndex = unitIndex + 1
            end
            configIndex = configIndex + 1
        end
    end
    return superFunc(xmlFile, customEnvironment, baseDir)
end
FillUnit.loadSpecValueFillTypes = Utils.overwrittenFunction(FillUnit.loadSpecValueFillTypes, onLoadSpecValueFillTypes)

local function balerOnLoad(vehicle, superFunc, savegame)
    if vehicle.xmlFile ~= nil then
        local vehicleType = string.upper(vehicle.xmlFile:getValue("vehicle#type", "") or "")
        if vehicleType == "BALERSTATIONARY" then
            buildFilteredOnce()
            local currentFillTypes = vehicle.xmlFile:getValue("vehicle.baler.additives#fillTypes")
            if currentFillTypes ~= nil then
                local upperTypes = string.upper(currentFillTypes)
                if upperTypes == "GRASS_WINDROW CHAFF" or upperTypes == "GRASS_WINDROW" then
                    vehicle.xmlFile:setValue("vehicle.baler.additives#fillTypes", FilltypeExtension._addBalStr)
                end
            end
        end
    end

    local returnedValue = superFunc(vehicle, savegame)

    if hasSpecialization(vehicle, "BalerStationary") then
        vehicle.spec_baler = vehicle.spec_baler or {}
        
        if vehicle.spec_baler.additives == nil then
            vehicle.spec_baler.additives = { enabled = false }
        elseif vehicle.spec_baler.additives.enabled == nil then
            vehicle.spec_baler.additives.enabled = false
        end
        
        if vehicle.spec_baler.variableSpeedLimit == nil then
            vehicle.spec_baler.variableSpeedLimit = { enabled = false }
        elseif vehicle.spec_baler.variableSpeedLimit.enabled == nil then
            vehicle.spec_baler.variableSpeedLimit.enabled = false
        end
    end

    return returnedValue
end
Baler.onLoad = Utils.overwrittenFunction(Baler.onLoad, balerOnLoad)

local function balerOnPostLoad(vehicle, superFunc, savegame)
    local returnedValue = superFunc(vehicle, savegame)
    if not hasSpecialization(vehicle, "BalerStationary") then
        return returnedValue
    end

    buildFilteredOnce()

    local function allowAllTypes(targetTable)
        if targetTable ~= nil then
            for _, fillTypeIndex in ipairs(FilltypeExtension._intakeIdx or {}) do
                targetTable[fillTypeIndex] = true
            end
        end
    end

    if vehicle.spec_baler ~= nil then
        allowAllTypes(vehicle.spec_baler.allowedFillTypes)
        allowAllTypes(vehicle.spec_baler.supportedFillTypes)
        allowAllTypes(vehicle.spec_baler.pickUpFillTypes)
    end

    local specBalerStationary = vehicle.spec_balerStationary or vehicle.spec_balerstationary
    if specBalerStationary ~= nil and specBalerStationary.supportedFillTypes ~= nil then
        allowAllTypes(specBalerStationary.supportedFillTypes)
    end

    return returnedValue
end
Baler.onPostLoad = Utils.overwrittenFunction(Baler.onPostLoad, balerOnPostLoad)

local function forageWagonOnLoad(vehicle, superFunc, savegame)
    if vehicle.xmlFile ~= nil then
        local vehicleType = string.upper(vehicle.xmlFile:getValue("vehicle#type", "") or "")
        if vehicleType == "FORAGEWAGON" then
            buildFilteredOnce()
            if vehicle.xmlFile:hasProperty("vehicle.forageWagon.additives") then
                local currentFillTypes = vehicle.xmlFile:getValue("vehicle.forageWagon.additives#fillTypes")
                if currentFillTypes ~= nil then
                    vehicle.xmlFile:setValue("vehicle.forageWagon.additives#fillTypes", FilltypeExtension._addFWStr)
                end
            end
        end
    end

    local returnedValue = superFunc(vehicle, savegame)

    if vehicle.spec_forageWagon ~= nil and vehicle.spec_forageWagon.additives ~= nil and vehicle.spec_forageWagon.additives.enabled == nil then
        vehicle.spec_forageWagon.additives.enabled = false
    end

    return returnedValue
end
ForageWagon.onLoad = Utils.overwrittenFunction(ForageWagon.onLoad, forageWagonOnLoad)

local function combineLoadCombineSetup(vehicle, superFunc, xmlFile, baseKey, entry)
    local vehicleType = string.upper(xmlFile:getValue("vehicle#type", "") or "")
    if vehicleType == "COMBINEDRIVABLE" or vehicleType == "COMBINE" then
        buildFilteredOnce()
        xmlFile:setValue("vehicle.combine.additives#fillTypes", FilltypeExtension._addFHStr)
    end
    return superFunc(vehicle, xmlFile, baseKey, entry)
end
Combine.loadCombineSetup = Utils.overwrittenFunction(Combine.loadCombineSetup, combineLoadCombineSetup)

local function combineOnLoad(vehicle, superFunc, savegame)
    local returnedValue = superFunc(vehicle, savegame)
    if vehicle.spec_combine ~= nil and vehicle.spec_combine.additives ~= nil and vehicle.spec_combine.additives.enabled == nil then
        vehicle.spec_combine.additives.enabled = false
    end
    return returnedValue
end
Combine.onLoad = Utils.overwrittenFunction(Combine.onLoad, combineOnLoad)
