-- Copyright ©2024-2025 by Todd Hundersmarck (ThundR) 
-- All Rights Reserved

--[[

Unauthorized use and/or distribution of this work entitles myself, the author, to unlimited free and unrestricted use, access, and distribution of any works related to the unauthorized user and/or distributor.

--]]

THSprayTypes = {}
local THSprayTypes_mt = Class(THSprayTypes)
THSprayTypes.CLASS_NAME = "THSprayTypes"
THSprayTypes.SPRAY_TYPE_GROUP = {
    FERTILIZER = 1,
    MANURE = 2,
    DIGESTATE = 3,
    LIME = 4,
    HERBICIDE = 5
}
THUtils.createEnumTable(THSprayTypes.SPRAY_TYPE_GROUP)
THSprayTypes.SPRAY_SUB_TYPE = {
    SOLID = 1,
    LIQUID = 2
}
THUtils.createEnumTable(THSprayTypes.SPRAY_SUB_TYPE)
local debugFlagId = THUtils.createDebugFlagId(THSprayTypes.CLASS_NAME)
THSprayTypes.debugFlagId = debugFlagId
local function initScript()
    local self = THSprayTypes.new()
    if self ~= nil then
        _G.g_thSprayTypes = self
    end
end
function THSprayTypes.new(customMt)
    customMt = customMt or THSprayTypes_mt
    local self = setmetatable({}, customMt)
    if self ~= nil then
        self.modulePath = "modules/sprayTypes/"
        self.userOnLoadValues = {
            modSprayTypes = {},
            extendedSprayTypes = {},
        }
        self.extendedSprayTypes = {
            byName = {},
            byIndex = {},
            bySprayTypeIndex = {},
            byGroup = {},
        }
        local sprayTypeGroups = THSprayTypes.SPRAY_TYPE_GROUP.getValues()
        for _, groupIndex in pairs(sprayTypeGroups) do
            self.extendedSprayTypes.byGroup[groupIndex] = {}
        end
        g_thEventManager:addEventListener(self)
        return self
    end
end
function THSprayTypes.onPostInit(self, ...)
    local modsArray, numLoadedMods = g_thModManager:getActiveMods()
    local modDescXMLKey = "modDesc." .. g_thPFConfig.coreData.xmlKey
    local modulePath = self.modulePath
    local absModulePath = g_thPFConfig.coreData.mod.path .. modulePath
    if modsArray ~= nil and numLoadedMods > 0 then
        for modIndex = 1, numLoadedMods do
            local modData = modsArray[modIndex]
            if modData.file ~= nil and modData.file ~= ""
                and modData.path ~= nil and modData.path ~= ""
            then
                if THUtils.getFileExists(modData.file) then
                    local modDescXMLFile = XMLFile.load(g_thPFConfig.coreData.name .. "ModDescXML", modData.file)
                    if modDescXMLFile ~= nil then
                        self:loadSprayTypesFromXML(modDescXMLFile, modDescXMLKey, modData.name, modData.path)
                        self:loadSprayTypeMappingFromXML(modDescXMLFile, modDescXMLKey, modData.name, modData.path)
                        modDescXMLFile:delete()
                    end
                end
            end
        end
    end
    local pfData = g_thPFConfig.precisionFarming
    if pfData.isFound then
        source(absModulePath .. "scripts/maps/THPHMap.lua")
        source(absModulePath .. "scripts/maps/THNitrogenMap.lua")
        source(absModulePath .. "scripts/gui/THExtendedSprayerHUDExtension.lua")
    end
    source(absModulePath .. "scripts/objects/THStorage.lua")
    source(absModulePath .. "scripts/objects/THLoadingStation.lua")
    source(absModulePath .. "scripts/objects/THUnloadingStation.lua")
end
function THSprayTypes.loadFromMapXML(self, xmlFile, xmlKey, customEnv, baseDirectory, ...)
    self:loadSprayTypeMappingFromXML(xmlFile, xmlKey, customEnv, baseDirectory, true)
    return true
end
function THSprayTypes.onLoadMapFinished(self, mission, ...)
    self.fillTypeConstants = g_thConstantMapping:initConstantMapping("fillTypes", "FillType", true)
    self.sprayTypeConstants = g_thConstantMapping:initConstantMapping("sprayTypes", "SprayType", true)
    self:finalizeExtendedSprayTypes()
    if THUtils.getIsDebugEnabled() then
        THUtils.displayMsg("")
        THUtils.displayMsg("THSprayTypes configuration:")
        THUtils.printTable(self)
        THUtils.displayMsg("User onLoad values:")
        THUtils.printTableValues(self.userOnLoadValues, 5)
        THUtils.displayMsg("Extended spray types:")
        THUtils.printTableValues(self.extendedSprayTypes.byIndex, 1)
    end
end
function THSprayTypes.loadSprayTypesFromXML(self, xmlFile, xmlKey, customEnv, baseDirectory, isMapMod)
    if THUtils.argIsValid(type(xmlFile) == THValueType.TABLE, "xmlFile", xmlFile)
        and THUtils.argIsValid(type(xmlKey) == THValueType.STRING, "xmlKey", xmlKey)
        and THUtils.argIsValid(type(customEnv) == THValueType.STRING, "customEnv", customEnv)
        and THUtils.argIsValid(type(baseDirectory) == THValueType.STRING, "baseDirectory", baseDirectory)
        and THUtils.argIsValid(not isMapMod or isMapMod == true, "isMapMod", isMapMod)
    then
        if not isMapMod then
            local onLoadValues = self.userOnLoadValues.modSprayTypes
            local sprayTypesKey = xmlKey .. ".sprayTypes"
            if xmlFile:hasProperty(sprayTypesKey) then
                xmlFile:iterate(sprayTypesKey .. ".sprayType", function(_, pSprayTypeKey)
                    local sprayTypeName = xmlFile:getString(pSprayTypeKey .. "#name")
                    local typeOfSpray = xmlFile:getString(pSprayTypeKey .. "#type")
                    local litersPerSecond = xmlFile:getFloat(pSprayTypeKey .. "#litersPerSecond")
                    local sprayGroundType = xmlFile:getString(pSprayTypeKey .. "#sprayGroundType")
                    local appRateKey = pSprayTypeKey .. ".applicationRate"
                    local fertUsageKey = pSprayTypeKey .. ".fertilizerUsage"
                    if sprayTypeName == nil or sprayTypeName == "" then
                        THUtils.xmlErrorMsg(pSprayTypeKey, nil, THMessage.MISSING_XML_KEY, "name")
                    elseif typeOfSpray == nil or typeOfSpray == "" then
                        THUtils.xmlErrorMsg(pSprayTypeKey, nil, THMessage.MISSING_XML_KEY, "type")
                    elseif litersPerSecond == nil or litersPerSecond <= 0 then
                        THUtils.xmlErrorMsg(pSprayTypeKey, nil, THMessage.VALUE_GREATER, "litersPerSecond", litersPerSecond, 0)
                    elseif sprayGroundType == nil or sprayGroundType == "" then
                        THUtils.xmlErrorMsg(pSprayTypeKey, nil, THMessage.MISSING_XML_KEY, "sprayGroundType")
                    else
                        sprayTypeName = string.upper(sprayTypeName)
                        local userData = onLoadValues[sprayTypeName]
                        if userData == nil then
                            userData = {
                                name = string.upper(sprayTypeName),
                                type = typeOfSpray,
                                litersPerSecond = litersPerSecond,
                                groundType = sprayGroundType,
                                isLoaded = false
                            }
                            onLoadValues[sprayTypeName] = userData
                            if xmlFile:hasProperty(appRateKey) then
                                local adjustToFruit = xmlFile:getBool(appRateKey .. "#autoAdjustToFruit")
                                local regularRate = xmlFile:getFloat(appRateKey .. "#regularRate")
                                if adjustToFruit ~= nil or regularRate ~= nil then
                                    local appRateData = {
                                        adjustToFruit = adjustToFruit == true,
                                        regularRate = regularRate,
                                        soilRates = {}
                                    }
                                    xmlFile:iterate(appRateKey .. ".soil", function(_, pSoilRateKey)
                                        local soilTypeIndex = xmlFile:getInt(pSoilRateKey .. "#soilTypeIndex")
                                        local soilRate = xmlFile:getFloat(pSoilRateKey .. "#rate")
                                        if soilRate ~= nil
                                            and soilTypeIndex ~= nil and soilTypeIndex >= 0
                                        then
                                            local soilRateData = {
                                                soilTypeIndex = soilTypeIndex,
                                                soilRate = soilRate
                                            }
                                            table.insert(appRateData.soilRates, soilRateData)
                                        end
                                    end)
                                    userData.pfApplicationRate = appRateData
                                end
                            end
                            if xmlFile:hasProperty(fertUsageKey) then
                                local nAmount = xmlFile:getFloat(fertUsageKey .. "#amount")
                                if nAmount ~= nil and nAmount >= 0 then
                                    userData.pfFertilizerUsage = {
                                        nAmount = nAmount
                                    }
                                end
                            end
                        end
                    end
                end)
            end
        end
    end
    return false
end
function THSprayTypes.loadSprayTypeMappingFromXML(self, xmlFile, xmlKey, customEnv, baseDirectory, isMapMod)
    if THUtils.argIsValid(type(xmlFile) == THValueType.TABLE, "xmlFile", xmlFile)
        and THUtils.argIsValid(type(xmlKey) == THValueType.STRING, "xmlKey", xmlKey)
        and THUtils.argIsValid(type(customEnv) == THValueType.STRING, "customEnv", customEnv)
        and THUtils.argIsValid(type(baseDirectory) == THValueType.STRING, "baseDirectory", baseDirectory)
        and THUtils.argIsValid(not isMapMod or isMapMod == true, "isMapMod", isMapMod)
    then
        local onLoadValues = self.userOnLoadValues.extendedSprayTypes
        local success = true
        local sprayTypeMappingKey = xmlKey .. ".sprayTypeMapping"
        if xmlFile:hasProperty(sprayTypeMappingKey) then
            xmlFile:iterate(sprayTypeMappingKey .. ".sprayType", function(_, pSprayTypeKey)
                local sprayTypeName = xmlFile:getString(pSprayTypeKey .. "#name")
                local groupName = xmlFile:getString(pSprayTypeKey .. "#group")
                if groupName == nil then
                    groupName = xmlFile:getString(pSprayTypeKey .. "#parent")
                end
                local subTypeName = xmlFile:getString(pSprayTypeKey .. "#subType")
                local subTypeIndex = nil
                if subTypeName ~= nil then
                    subTypeIndex = THSprayTypes.SPRAY_SUB_TYPE.getValue(subTypeName)
                else
                    local isLiquid = xmlFile:getBool(pSprayTypeKey .. "#isLiquid")
                    if isLiquid then
                        subTypeIndex = THSprayTypes.SPRAY_SUB_TYPE.LIQUID
                    else
                        subTypeIndex = THSprayTypes.SPRAY_SUB_TYPE.SOLID
                    end
                end
                if sprayTypeName == nil or sprayTypeName == "" then
                    THUtils.xmlErrorMsg(pSprayTypeKey, nil, THMessage.MISSING_XML_KEY, "name")
                elseif groupName == nil or groupName == "" then
                    THUtils.xmlErrorMsg(pSprayTypeKey, nil, THMessage.MISSING_XML_KEY, "group")
                else
                    sprayTypeName = string.upper(sprayTypeName)
                    groupName = string.upper(groupName)
                    local altGroupName, nFound = string.gsub(groupName, "LIQUID", "")
                    if altGroupName ~= nil and nFound ~= nil and nFound > 0 then
                        if THSprayTypes.SPRAY_TYPE_GROUP.getValue(altGroupName) ~= nil then
                            groupName = altGroupName
                            subTypeIndex = THSprayTypes.SPRAY_SUB_TYPE.LIQUID
                        end
                    end
                    local groupIndex = THSprayTypes.SPRAY_TYPE_GROUP.getValue(groupName)
                    if groupIndex == nil then
                        THUtils.xmlErrorMsg(pSprayTypeKey, nil, "Invalid group (%s) for spray type: %q", groupName, sprayTypeName)
                    else
                        local onLoadData = onLoadValues[sprayTypeName]
                        if onLoadData == nil then
                            onLoadData = {
                                name = sprayTypeName,
                                groupIndex = groupIndex,
                                subTypeIndex = subTypeIndex
                            }
                            onLoadValues[sprayTypeName] = onLoadData
                        end
                    end
                end
            end)
        end
        return success
    end
    return false
end
function THSprayTypes.finalizeExtendedSprayTypes(self)
    for sprayTypeName, sprayUserData in pairs(self.userOnLoadValues.modSprayTypes) do
        local otherSprayTypeDesc = g_sprayTypeManager:getSprayTypeByName(sprayTypeName)
        if otherSprayTypeDesc == nil and not sprayUserData.isLoaded then
            local thSprayFillTypeData = g_thMapTypeManager:getFillType(sprayUserData.name)
            local sprayGroundType = FieldSprayType.getValueByName(sprayUserData.groundType)
            if thSprayFillTypeData == nil then
                THUtils.errorMsg(nil, "Spray fill type %q does not exist", sprayUserData.name)
            elseif sprayGroundType == nil then
                THUtils.errorMsg(nil, "Could not find spray ground type: %s", sprayUserData.groundType)
            else
                g_sprayTypeManager:addSprayType(sprayUserData.name, sprayUserData.litersPerSecond, sprayUserData.type, sprayGroundType)
                THUtils.displayMsg("Injecting spray type: %s", sprayUserData.name)
                sprayUserData.isLoaded = true
            end
        end
    end
    local sprayTypesArray = g_sprayTypeManager:getSprayTypes()
    if sprayTypesArray ~= nil then
        for _, sprayTypeDesc in pairs(sprayTypesArray) do
            if type(sprayTypeDesc.name) == THValueType.STRING and sprayTypeDesc.name ~= ""
                and sprayTypeDesc.fillType ~= nil
            then
                local sprayTypeName = string.upper(sprayTypeDesc.name)
                local thFillTypeData = g_thMapTypeManager:getFillType(sprayTypeDesc.fillType)
                if self.extendedSprayTypes.byName[sprayTypeName] == nil
                    and thFillTypeData ~= nil and thFillTypeData.index ~= FillType.UNKNOWN
                then
                    local fillTypeIndex = thFillTypeData.index
                    local sprayOnLoadValues = self.userOnLoadValues.extendedSprayTypes[thFillTypeData.name]
                    local groupIndex, subTypeIndex = nil, THSprayTypes.SPRAY_SUB_TYPE.SOLID
                    if fillTypeIndex == FillType.FERTILIZER or fillTypeIndex == FillType.LIQUIDFERTILIZER then
                        groupIndex = THSprayTypes.SPRAY_TYPE_GROUP.FERTILIZER
                    elseif fillTypeIndex == FillType.MANURE or fillTypeIndex == FillType.LIQUIDMANURE then
                        groupIndex = THSprayTypes.SPRAY_TYPE_GROUP.MANURE
                    elseif fillTypeIndex == FillType.DIGESTATE then
                        groupIndex = THSprayTypes.SPRAY_TYPE_GROUP.DIGESTATE
                    elseif fillTypeIndex == FillType.LIME then
                        groupIndex = THSprayTypes.SPRAY_TYPE_GROUP.LIME
                    elseif fillTypeIndex == FillType.HERBICIDE then
                        groupIndex = THSprayTypes.SPRAY_TYPE_GROUP.HERBICIDE
                    elseif sprayOnLoadValues ~= nil then
                        groupIndex = sprayOnLoadValues.groupIndex
                    end
                    if fillTypeIndex == FillType.LIQUIDFERTILIZER
                        or fillTypeIndex == FillType.LIQUIDMANURE
                        or fillTypeIndex == FillType.DIGESTATE
                        or fillTypeIndex == FillType.HERBICIDE
                    then
                        subTypeIndex = THSprayTypes.SPRAY_SUB_TYPE.LIQUID
                    elseif fillTypeIndex == FillType.FERTILIZER
                        or fillTypeIndex == FillType.MANURE
                        or fillTypeIndex == FillType.LIME
                    then
                        subTypeIndex = THSprayTypes.SPRAY_SUB_TYPE.SOLID
                    elseif sprayOnLoadValues ~= nil
                        and sprayOnLoadValues.subTypeIndex ~= nil
                    then
                        subTypeIndex = sprayOnLoadValues.subTypeIndex
                    else
                        subTypeIndex = THSprayTypes.SPRAY_SUB_TYPE.SOLID
                    end
                    if groupIndex ~= nil then
                        local baseSprayTypeIndex, baseFillTypeIndex = nil, nil
                        if groupIndex == THSprayTypes.SPRAY_TYPE_GROUP.FERTILIZER then
                            if subTypeIndex == THSprayTypes.SPRAY_SUB_TYPE.LIQUID then
                                baseSprayTypeIndex = SprayType.LIQUIDFERTILIZER
                                baseFillTypeIndex = FillType.LIQUIDFERTILIZER
                            else
                                baseSprayTypeIndex = SprayType.FERTILIZER
                                baseFillTypeIndex = FillType.FERTILIZER
                            end
                        elseif groupIndex == THSprayTypes.SPRAY_TYPE_GROUP.MANURE then
                            if subTypeIndex == THSprayTypes.SPRAY_SUB_TYPE.LIQUID then
                                baseSprayTypeIndex = SprayType.LIQUIDMANURE
                                baseFillTypeIndex = FillType.LIQUIDMANURE
                            else
                                baseSprayTypeIndex = SprayType.MANURE
                                baseFillTypeIndex = FillType.MANURE
                            end
                        else
                            local groupName = THSprayTypes.SPRAY_TYPE_GROUP.getId(groupIndex)
                            if groupName ~= nil then
                                baseSprayTypeIndex = SprayType[groupName]
                                baseFillTypeIndex = FillType[groupName]
                            end
                        end
                        if baseSprayTypeIndex ~= nil and baseFillTypeIndex ~= nil then
                            local thBaseFillTypeData = g_thMapTypeManager:getFillType(baseFillTypeIndex)
                            local baseSprayTypeDesc = g_sprayTypeManager:getSprayTypeByIndex(baseSprayTypeIndex)
                            if thBaseFillTypeData ~= nil then
                                local baseRate = THUtils.toNumber(baseSprayTypeDesc.litersPerSecond) or 0
                                local usageFactor = 1
                                if baseRate > 0 then
                                    local sprayRate = THUtils.toNumber(sprayTypeDesc.litersPerSecond) or 0
                                    usageFactor = math.max(sprayRate / baseRate, 0.001)
                                end
                                local xtSprayTypeData = {
                                    name = sprayTypeName,
                                    index = #self.extendedSprayTypes.byIndex + 1,
                                    sprayType = sprayTypeDesc,
                                    fillType = thFillTypeData,
                                    baseSprayType = baseSprayTypeDesc,
                                    baseFillType = thBaseFillTypeData,
                                    groupIndex = groupIndex,
                                    subTypeIndex = subTypeIndex,
                                    isBaseType = thFillTypeData.index == thBaseFillTypeData.index,
                                    usageFactor = usageFactor
                                }
                                function xtSprayTypeData.activateMapping(pSelf, pMapSprayType, pMapFillType, pAltDebugFlagId, pAltDebugLevel)
                                    local vSprayTypeSuccess = false
                                    local vFillTypeSuccess = false
                                    if pMapSprayType == nil or pMapSprayType == true then
                                        if not pSelf.isBaseType then
                                            vSprayTypeSuccess = g_thConstantMapping:mapConstant("sprayTypes", pSelf.baseSprayType.name, pSelf.sprayType.index, pAltDebugFlagId, pAltDebugLevel)
                                        end
                                    elseif pMapSprayType ~= false then
                                        THUtils.errorMsg(true, THMessage.ARGUMENT_INVALID, "mapSprayType", pMapSprayType)
                                        vSprayTypeSuccess = false
                                    end
                                    if pMapFillType == nil or pMapFillType == true then
                                        if not pSelf.isBaseType then
                                            vFillTypeSuccess = g_thConstantMapping:mapConstant("fillTypes", pSelf.baseFillType.name, pSelf.fillType.index, pAltDebugFlagId, pAltDebugLevel)
                                        end
                                    elseif pMapFillType ~= false then
                                        THUtils.errorMsg(true, THMessage.ARGUMENT_INVALID, "mapFillType", pMapFillType)
                                        vFillTypeSuccess = false
                                    end
                                    return vSprayTypeSuccess == true, vFillTypeSuccess == true
                                end
                                function xtSprayTypeData.resetMapping(_, pAltDebugFlagId, pAltDebugLevel)
                                    local vSprayTypeSuccess = g_thConstantMapping:resetConstantMapping("sprayTypes", pAltDebugFlagId, pAltDebugLevel)
                                    local vFillTypeSuccess = g_thConstantMapping:resetConstantMapping("fillTypes", pAltDebugFlagId, pAltDebugLevel)
                                    return vSprayTypeSuccess, vFillTypeSuccess
                                end
                                self.extendedSprayTypes.byName[xtSprayTypeData.name] = xtSprayTypeData
                                self.extendedSprayTypes.byIndex[xtSprayTypeData.index] = xtSprayTypeData
                                self.extendedSprayTypes.bySprayTypeIndex[xtSprayTypeData.sprayType.index] = xtSprayTypeData
                                local groupSprayTypesArray = self.extendedSprayTypes.byGroup[xtSprayTypeData.groupIndex]
                                if groupSprayTypesArray == nil then
                                    groupSprayTypesArray = {}
                                    self.extendedSprayTypes.byGroup[xtSprayTypeData.groupIndex] = groupSprayTypesArray
                                end
                                table.insert(groupSprayTypesArray, xtSprayTypeData)
                                THUtils.displayMsg("Mapping spray type %q to %q", xtSprayTypeData.name, xtSprayTypeData.baseFillType.name)
                            end
                        end
                    end
                end
            end
        end
    end
end
function THSprayTypes.getExtendedSprayType(self, sprayTypeId, verbose)
    local idVarType = type(sprayTypeId)
    local xtSprayTypeData = nil
    verbose = THUtils.validateArg(not verbose or verbose == true, "verbose", verbose, true)
    if idVarType == THValueType.STRING then
        xtSprayTypeData = self.extendedSprayTypes.byName[sprayTypeId:upper()]
    elseif idVarType == THValueType.NUMBER then
        xtSprayTypeData = self.extendedSprayTypes.bySprayTypeIndex[sprayTypeId]
    elseif sprayTypeId ~= nil then
        verbose = true
    end
    if xtSprayTypeData == nil and verbose then
        THUtils.errorMsg(true, THMessage.ARGUMENT_INVALID, "sprayTypeId", sprayTypeId)
    end
    return xtSprayTypeData
end
function THSprayTypes.getExtendedSprayTypeByFillType(self, fillTypeId, verbose)
    local thFillTypeData = g_thMapTypeManager:getFillType(fillTypeId, verbose)
    if thFillTypeData ~= nil and thFillTypeData.index ~= FillType.UNKNOWN then
        local sprayTypeDesc = g_sprayTypeManager:getSprayTypeByFillTypeIndex(thFillTypeData.index)
        if sprayTypeDesc ~= nil then
            return self:getExtendedSprayType(sprayTypeDesc.name, verbose)
        end
    end
end
function THSprayTypes.getExtendedSprayTypes(self, groupId)
    if groupId == nil then
        return self.extendedSprayTypes.byIndex, #self.extendedSprayTypes.byIndex
    end
    local groupIdVarType = type(groupId)
    local groupIndex = nil
    if groupIdVarType == THValueType.STRING then
        groupIndex = THSprayTypes.SPRAY_TYPE_GROUP.getValue(groupId)
    elseif groupIdVarType == THValueType.NUMBER then
        if THSprayTypes.SPRAY_TYPE_GROUP.getId(groupId) then
            groupIndex = groupId
        end
    end
    if groupIndex ~= nil then
        local groupSprayTypes = self.extendedSprayTypes.byGroup[groupIndex]
        if groupSprayTypes ~= nil then
            return groupSprayTypes, #groupSprayTypes
        end
    end
    THUtils.errorMsg(true, THMessage.ARGUMENT_INVALID, "groupId", groupId)
    return nil, 0
end
function THSprayTypes.addExtendedSprayTypesToFillTypeList(self, sourceNames, sourceCategories, isArray, allowAllSolids, allowAllLiquids)
    if THUtils.argIsValid(not isArray or isArray == true, "isArray", isArray)
        and THUtils.argIsValid(not allowAllSolids or allowAllSolids == true, "allowAllSolids", allowAllSolids)
        and THUtils.argIsValid(not allowAllLiquids or allowAllLiquids == true, "allowAllLiquids", allowAllLiquids)
    then
        local namesType = type(sourceNames)
        local categoriesType = type(sourceCategories)
        local fillTypesArray, fillTypeList = nil, nil
        local hasSprayTypes, hasSolids, hasLiquids = false, false, false
        local function addFillTypeToArray(pFillTypeId, pFillTypeValues)
            local thFillTypeData = g_thMapTypeManager:getFillType(pFillTypeId)
            if thFillTypeData ~= nil and thFillTypeData.index ~= FillType.UNKNOWN then
                pFillTypeValues = THUtils.getNoNil(pFillTypeValues, true)
                fillTypesArray = fillTypesArray or {}
                fillTypeList = fillTypeList or {}
                if not fillTypeList[thFillTypeData.name] then
                    table.insert(fillTypesArray, thFillTypeData.name)
                    fillTypeList[thFillTypeData.name] = pFillTypeValues
                    local xtSprayTypeData = self:getExtendedSprayTypeByFillType(thFillTypeData.index)
                    if xtSprayTypeData ~= nil then
                        hasSprayTypes = true
                        if xtSprayTypeData.subTypeIndex == THSprayTypes.SPRAY_SUB_TYPE.LIQUID then
                            hasLiquids = true
                        else
                            hasSolids = true
                        end
                    end
                end
            end
        end
        if namesType == THValueType.TABLE then
            if isArray then
                for _, fillTypeId in ipairs(sourceNames) do
                    addFillTypeToArray(fillTypeId)
                end
            else
                for fillTypeId, fillTypeValues in pairs(sourceNames) do
                    if sourceCategories == nil then
                        addFillTypeToArray(fillTypeId, fillTypeValues)
                    else
                        addFillTypeToArray(fillTypeId)
                    end
                end
            end
        elseif namesType == THValueType.STRING then
            local srcFillTypesArray = THUtils.splitString(sourceNames)
            for _, fillTypeId in ipairs(srcFillTypesArray) do
                addFillTypeToArray(fillTypeId)
            end
        elseif sourceNames ~= nil then
            THUtils.errorMsg(true, THMessage.ARGUMENT_INVALID, "sourceNames", sourceNames)
            return
        end
        if sourceCategories ~= nil then
            local categoryFillTypes = nil
            if categoriesType == THValueType.TABLE then
                categoryFillTypes = g_fillTypeManager:getFillTypesByCategoryNamesList(sourceCategories)
            elseif categoriesType == THValueType.STRING then
                categoryFillTypes = g_fillTypeManager:getFillTypesByCategoryNames(sourceCategories)
            else
                THUtils.errorMsg(true, THMessage.ARGUMENT_INVALID, "sourceCategories", sourceCategories)
                return
            end
            if categoryFillTypes ~= nil then
                for _, fillTypeId in ipairs(categoryFillTypes) do
                    addFillTypeToArray(fillTypeId)
                end
            end
        end
        if hasSprayTypes and fillTypeList ~= nil
            and fillTypesArray ~= nil and #fillTypesArray > 0
        then
            local xtSprayTypesArray = self:getExtendedSprayTypes()
            local hasExtendedSprayTypes = false
            for _, xtSprayTypeData in ipairs(xtSprayTypesArray) do
                if not xtSprayTypeData.isBaseType
                    and fillTypeList[xtSprayTypeData.fillType.name] == nil
                then
                    if (hasSolids and xtSprayTypeData.subTypeIndex == THSprayTypes.SPRAY_SUB_TYPE.SOLID)
                        or (hasLiquids and xtSprayTypeData.subTypeIndex == THSprayTypes.SPRAY_SUB_TYPE.LIQUID)
                    then
                        local baseValues = fillTypeList[xtSprayTypeData.baseFillType.name]
                        if not baseValues and allowAllSolids then
                            if xtSprayTypeData.groupIndex == THSprayTypes.SPRAY_TYPE_GROUP.DIGESTATE then
                                if fillTypeList.MANURE
                                    and (fillTypeList.LIME or fillTypeList.FERTILIZER)
                                then
                                    baseValues = fillTypeList.MANURE
                                end
                            elseif xtSprayTypeData.groupIndex == THSprayTypes.SPRAY_TYPE_GROUP.HERBICIDE then
                                if fillTypeList.FERTILIZER
                                    and (fillTypeList.LIME or fillTypeList.MANURE)
                                then
                                    baseValues = fillTypeList.FERTILIZER
                                end
                            end
                        end
                        if not baseValues and allowAllLiquids then
                            if xtSprayTypeData.groupIndex == THSprayTypes.SPRAY_TYPE_GROUP.LIME then
                                if fillTypeList.LIQUIDFERTILIZER
                                    and (fillTypeList.HERBICIDE or fillTypeList.LIQUIDMANURE or fillTypeList.DIGESTATE)
                                then
                                    baseValues = fillTypeList.LIQUIDFERTILIZER
                                end
                            end
                        end
                        if baseValues then
                            addFillTypeToArray(xtSprayTypeData.fillType.name, baseValues)
                            hasExtendedSprayTypes = true
                        end
                    end
                end
            end
            if hasExtendedSprayTypes then
                local fillTypeNames = nil
                for _, fillTypeId in ipairs(fillTypesArray) do
                    local thFillTypeData = g_thMapTypeManager:getFillType(fillTypeId)
                    if thFillTypeData ~= nil then
                        if fillTypeNames == nil then
                            fillTypeNames = thFillTypeData.name
                        else
                            fillTypeNames = fillTypeNames .. " " .. thFillTypeData.name
                        end
                    end
                end
                if fillTypeNames ~= nil and fillTypeNames ~= "" then
                    return fillTypeNames, fillTypeList, fillTypesArray
                end
            end
        end
    end
end
function THSprayTypes.resetExtendedSprayTypeConstants(_, altDebugFlagId, altDebugLevel)
    g_thConstantMapping:resetConstantMapping("sprayTypes", altDebugFlagId, altDebugLevel)
    g_thConstantMapping:resetConstantMapping("fillTypes", altDebugFlagId, altDebugLevel)
end
THUtils.pcall(initScript)