-- One-time warning when the external FS25_Puncture mod is active.
-- No external setting is changed automatically.

PunctureModConflictDialog = {}
PunctureModConflictDialog.NOTICE_VERSION = 1
PunctureModConflictDialog.NOTICE_FILENAME = "mudSystemPhysicsNotices.xml"
PunctureModConflictDialog.MOD_NAMES = {
    "FS25_Puncture"
}

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

function PunctureModConflictDialog:isExternalPunctureActive()
    for _, modName in ipairs(self.MOD_NAMES) do
        if g_modIsLoaded ~= nil and g_modIsLoaded[modName] then
            return true, modName
        end
    end

    local mission = g_currentMission
    local dynamicInfo = (mission ~= nil and mission.missionDynamicInfo)
        or (g_mpLoadingScreen ~= nil and g_mpLoadingScreen.missionDynamicInfo)
    local mods = dynamicInfo ~= nil and dynamicInfo.mods or nil
    if mods ~= nil then
        for _, modInfo in pairs(mods) do
            for _, modName in ipairs(self.MOD_NAMES) do
                if modInfo ~= nil and modInfo.modName == modName then
                    return true, modName
                end
            end
        end
    end

    if rawget(_G, "FS25_Puncture") ~= nil then
        return true, "runtime"
    end
    return false, nil
end

function PunctureModConflictDialog:isClient()
    local mission = g_currentMission
    if mission ~= nil and mission.getIsClient ~= nil then
        return mission:getIsClient()
    end
    return g_gui ~= nil
end

function PunctureModConflictDialog:getNoticePath()
    local missionInfo = g_currentMission ~= nil
        and g_currentMission.missionInfo or nil
    local savegameDirectory = missionInfo ~= nil
        and missionInfo.savegameDirectory or nil
    if savegameDirectory == nil or savegameDirectory == "" then return nil end
    return Utils.getFilename(self.NOTICE_FILENAME, savegameDirectory)
end

function PunctureModConflictDialog:getShownVersion()
    local path = self:getNoticePath()
    if path == nil or not fileExists(path) then return 0 end

    local xmlFile = loadXMLFile("MudSystemPhysicsNotices", path)
    if xmlFile == 0 then return 0 end
    local version = getXMLInt(
        xmlFile,
        "mudSystemPhysicsNotices.externalPunctureConflict#version"
    ) or 0
    delete(xmlFile)
    return version
end

function PunctureModConflictDialog:markShown()
    local path = self:getNoticePath()
    if path == nil then
        Logging.warning(
            "[MudSystemPhysics] Could not resolve savegame directory for puncture conflict notice"
        )
        return
    end

    local xmlFile = fileExists(path)
        and loadXMLFile("MudSystemPhysicsNotices", path)
        or createXMLFile(
            "MudSystemPhysicsNotices",
            path,
            "mudSystemPhysicsNotices"
        )
    if xmlFile == 0 then
        Logging.warning(
            "[MudSystemPhysics] Could not save puncture conflict notice state"
        )
        return
    end

    setXMLInt(
        xmlFile,
        "mudSystemPhysicsNotices.externalPunctureConflict#version",
        self.NOTICE_VERSION
    )
    saveXMLFile(xmlFile)
    delete(xmlFile)
end

function PunctureModConflictDialog:showDialog(onComplete)
    local text = pmcdGetText(
        "mudsys_puncture_mod_conflict_text",
        "FS25_Puncture is active. Running two puncture systems can cause duplicate punctures, conflicting speed limits and incompatible repair states. We recommend disabling FS25_Puncture and enabling Wheel punctures in the Mud System Physics settings."
    )
    local okText = pmcdGetText("mudsys_puncture_mod_conflict_ok", "OK")

    local function closeNotice()
        PunctureModConflictDialog:markShown()
        if onComplete ~= nil then onComplete() end
    end

    if InfoDialog ~= nil and InfoDialog.show ~= nil
        and InfoDialog.INSTANCE ~= nil then
        InfoDialog.show(
            text,
            closeNotice,
            nil,
            DialogElement ~= nil and DialogElement.TYPE_WARNING or nil,
            okText
        )
        return true
    end

    print("[MudSystemPhysics] " .. text)
    closeNotice()
    return false
end

function PunctureModConflictDialog:loadMap()
    if not self:isClient()
        or self:getShownVersion() >= self.NOTICE_VERSION then return end

    local active, detectedAs = self:isExternalPunctureActive()
    if not active then return end

    print(string.format(
        "[MudSystemPhysics] External puncture system detected (%s)",
        tostring(detectedAs)
    ))

    if MudSystemDialogQueue ~= nil and MudSystemDialogQueue.enqueue ~= nil then
        MudSystemDialogQueue:enqueue(
            "externalPunctureConflict",
            90,
            function(onComplete)
                return PunctureModConflictDialog:showDialog(onComplete)
            end
        )
    else
        self:showDialog(nil)
    end
end

addModEventListener(PunctureModConflictDialog)
