DiseaseSoilMap = {}
DiseaseSoilMap.MOD_NAME = g_currentModName or "FS25_CropDiseases_BMP"

DiseaseSoilMap.LAYER_INDEX = {
    DISEASE = 1,
    PEST = 2
}

DiseaseSoilMap.OVERLAY_MAP_DISEASE = "bmpSoilDiseaseOverlay"
DiseaseSoilMap.OVERLAY_MAP_PEST = "bmpSoilPestOverlay"

DiseaseSoilMap.COLORS = {
    disease = {
        [false] = {
            {0.18, 0.78, 0.18, 1},
            {0.94, 0.82, 0.18, 1},
            {0.55, 0.34, 0.16, 1},
            {0.86, 0.14, 0.10, 1}
        },
        [true] = {
            {0.18, 0.78, 0.18, 1},
            {0.94, 0.82, 0.18, 1},
            {0.55, 0.34, 0.16, 1},
            {0.86, 0.14, 0.10, 1}
        }
    },
    pest = {
        [false] = {
            {0.18, 0.68, 0.22, 1},
            {0.95, 0.60, 0.14, 1},
            {0.73, 0.31, 0.67, 1},
            {0.47, 0.05, 0.14, 1}
        },
        [true] = {
            {0.18, 0.68, 0.22, 1},
            {0.95, 0.60, 0.14, 1},
            {0.73, 0.31, 0.67, 1},
            {0.47, 0.05, 0.14, 1}
        }
    }
}

local function getL10nText(key, fallback)
    if g_i18n ~= nil and g_i18n.hasText ~= nil and g_i18n:hasText(key) then
        return g_i18n:getText(key)
    end

    return fallback
end

local function resetOverlay(overlayId)
    if overlayId == nil or overlayId == 0 then
        return
    end

    resetDensityMapVisualizationOverlay(overlayId)
    setOverlayColor(overlayId, 1, 1, 1, 1)
end

local function setMapPoint(mapId, x, z, value)
    setBitVectorMapParallelogram(mapId, x, z, 1, 0, 0, 1, 0, 2, value)
end

local function clearMap(mapId, width, height)
    if mapId == nil or width == nil or height == nil then
        return
    end

    setBitVectorMapParallelogram(mapId, 0, 0, width, 0, 0, height, 0, 2, 0)
end

local function getOrCreateOverlayMap(name, width, height)
    DiseaseSoilMap.overlayMaps = DiseaseSoilMap.overlayMaps or {}

    local entry = DiseaseSoilMap.overlayMaps[name]
    if entry ~= nil and entry.mapId ~= nil and entry.width == width and entry.height == height then
        return entry.mapId
    end

    if entry ~= nil and entry.mapId ~= nil then
        delete(entry.mapId)
    end

    local mapId = createBitVectorMap(name)
    loadBitVectorMapNew(mapId, width, height, 2, false)

    DiseaseSoilMap.overlayMaps[name] = {
        mapId = mapId,
        width = width,
        height = height
    }

    return mapId
end

local function rebuildCategoryOverlayMap(category)
    if DiseaseGrid == nil or DiseaseGrid.mapId == nil or DiseaseGrid.width == nil or DiseaseGrid.height == nil then
        return nil
    end

    local defs = _G.DiseaseDefs
    if defs == nil then
        return nil
    end

    local mapName = category == "pest" and DiseaseSoilMap.OVERLAY_MAP_PEST or DiseaseSoilMap.OVERLAY_MAP_DISEASE
    local targetMapId = getOrCreateOverlayMap(mapName, DiseaseGrid.width, DiseaseGrid.height)
    clearMap(targetMapId, DiseaseGrid.width, DiseaseGrid.height)

    for z = 0, DiseaseGrid.height - 1 do
        for x = 0, DiseaseGrid.width - 1 do
            local severity = getBitVectorMapPoint(DiseaseGrid.mapId, x, z, 0, 2) or 0
            if severity > 0 then
                local threatId = getBitVectorMapPoint(DiseaseGrid.mapId, x, z, 2, 4) or 0
                local threatKey = defs.getThreatKeyById and defs:getThreatKeyById(threatId) or nil
                local threatCategory = threatKey and defs.getThreatCategory and defs:getThreatCategory(threatKey) or nil
                if threatCategory == category then
                    setMapPoint(targetMapId, x, z, severity)
                end
            end
        end
    end

    return targetMapId
end

local function applyHealthyFieldBase(overlayId, color)
    if g_currentMission == nil or g_currentMission.fieldGroundSystem == nil or overlayId == nil or color == nil then
        return
    end

    local groundTypeMapId, firstChannel, numChannels = g_currentMission.fieldGroundSystem:getDensityMapData(FieldDensityMap.GROUND_TYPE)
    if groundTypeMapId == nil or firstChannel == nil or numChannels == nil then
        return
    end

    local maxValue = bit32.lshift(1, numChannels) - 1
    for value = 1, maxValue do
        setDensityMapVisualizationOverlayStateColor(
            overlayId,
            groundTypeMapId,
            0,
            0,
            firstChannel,
            numChannels,
            value,
            color[1],
            color[2],
            color[3]
        )
    end
end

local function applySeverityColors(overlayId, mapId, colorSet)
    if overlayId == nil or overlayId == 0 or mapId == nil or colorSet == nil then
        return
    end

    for severity = 1, 3 do
        local color = colorSet[severity + 1] or colorSet[#colorSet]
        if color ~= nil then
            setDensityMapVisualizationOverlayStateColor(
                overlayId,
                mapId,
                0,
                0,
                0,
                2,
                severity,
                color[1],
                color[2],
                color[3]
            )
        end
    end
end

function DiseaseSoilMap.getDisplayThreatStates()
    local isActive = DiseaseGrid ~= nil and DiseaseGrid.mapId ~= nil

    return {
        [DiseaseSoilMap.LAYER_INDEX.DISEASE] = {
            colors = DiseaseSoilMap.COLORS.disease,
            description = getL10nText("bmp_mapLayerDiseases", "Diseases"),
            isActive = isActive
        },
        [DiseaseSoilMap.LAYER_INDEX.PEST] = {
            colors = DiseaseSoilMap.COLORS.pest,
            description = getL10nText("bmp_mapLayerPests", "Pests"),
            isActive = isActive
        }
    }
end

function DiseaseSoilMap.buildThreatOverlays(baseOverlayId, diseaseOverlayId, pestOverlayId, layerFilter, isColorBlindMode)
    resetOverlay(baseOverlayId)
    resetOverlay(diseaseOverlayId)
    resetOverlay(pestOverlayId)

    if DiseaseGrid == nil or DiseaseGrid.mapId == nil or layerFilter == nil then
        return
    end

    local showDiseases = layerFilter[DiseaseSoilMap.LAYER_INDEX.DISEASE] == true
    local showPests = layerFilter[DiseaseSoilMap.LAYER_INDEX.PEST] == true

    if not showDiseases and not showPests then
        return
    end

    local colorBlind = isColorBlindMode == true
    local diseaseColors = DiseaseSoilMap.COLORS.disease[colorBlind] or DiseaseSoilMap.COLORS.disease[false]
    local pestColors = DiseaseSoilMap.COLORS.pest[colorBlind] or DiseaseSoilMap.COLORS.pest[false]

    if showDiseases then
        applyHealthyFieldBase(baseOverlayId, diseaseColors[1])
        applySeverityColors(diseaseOverlayId, rebuildCategoryOverlayMap("disease"), diseaseColors)
    elseif showPests then
        applyHealthyFieldBase(baseOverlayId, pestColors[1])
    end

    if showPests then
        applySeverityColors(pestOverlayId, rebuildCategoryOverlayMap("pest"), pestColors)
    end
end

