-- 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.

--]]

local g_thModName = g_currentModName
local g_thModPath = g_currentModDirectory
source(g_thModPath .. "shared/scripts/utilities/THUtils.lua")
source(g_thModPath .. "shared/scripts/managers/THModManager.lua")
source(g_thModPath .. "shared/scripts/managers/THEventManager.lua")
THCore = {}
local THCore_mt = Class(THCore)
local debugFlagId = THUtils.createDebugFlagId("SELF")
THCore.debugFlagId = debugFlagId
function THCore.new(name, customMt)
    customMt = customMt or THCore_mt
    if THUtils.argIsValid(THUtils.isValidName(name) == true, "name", name)
        and THUtils.argIsValid(type(customMt) == THValueType.TABLE, "customMt", customMt)
    then
        local self = setmetatable({}, customMt)
        local coreData = {
            isServer = g_server ~= nil,
            isClient = g_client ~= nil,
            name = name,
            xmlKey = name,
            managers = {
                xml = g_xmlManager,
                fruitTypes = g_fruitTypeManager,
                fillTypes = g_fillTypeManager,
                fields = g_fieldManager
            },
            thirdPartyMods = {},
            isExistingSave = false,
        }
        self.coreData = coreData
        local mpLoadingScreen = g_mpLoadingScreen
        local missionInfo = mpLoadingScreen.missionInfo
        local missionDynamicInfo = mpLoadingScreen.missionDynamicInfo
        coreData.missionInfo = missionInfo
        coreData.missionDynamicInfo = missionDynamicInfo
        local modData = g_thModManager:getActiveMod(g_thModName)
        if modData == nil then
            THUtils.errorMsg(true, "Cannot find mod environment: %s", g_thModName)
            return
        end
        local mapDesc = coreData.missionInfo.map
        local isModMap = mapDesc.isModMap == true
        local mapData = {
            desc = mapDesc,
            path = mapDesc.baseDirectory,
            xmlFilename = mapDesc.mapXMLFilename,
        }
        local mapId = THUtils.toString(mapDesc.id)
        mapData.id = string.upper(mapId)
        mapData.name = mapData.id
        if isModMap
            and type(mapDesc.customEnvironment) == THValueType.STRING and mapDesc.customEnvironment ~= ""
        then
            local mapModData = g_thModManager:getActiveMod(mapDesc.customEnvironment)
            if mapModData ~= nil then
                mapData.mod = mapModData
            end
        end
        isModMap = mapData.mod ~= nil
        mapData.isMod = isModMap == true
        if type(self.class) == THValueType.FUNCTION then
            local classTable = self:class()
            if classTable ~= nil and classTable ~= THCore then
                coreData.dataKey = tostring(classTable)
            end
        end
        coreData.dataKey = coreData.dataKey or modData.name .. "." .. name
        coreData.mod = modData
        coreData.map = mapData
        local mapSettingsModName = string.format("FS%d_TH_MapSettings", THGameVersion)
        local mapSettingsModData = g_thModManager:getActiveMod(mapSettingsModName)
        if mapSettingsModData ~= nil then
            local mapSettingsData = {
                mod = mapSettingsModData,
                xmlFilename = mapSettingsModData.path .. "maps/mapSettings.xml",
                xmlRootKey = "thMapSettings"
            }
            coreData.mapSettings = mapSettingsData
        end
        local xmlManager = coreData.managers.xml
        xmlManager:addCreateSchemaFunction(function()
            if coreData.xmlSchemaMap == nil then
                coreData.xmlSchemaMap = XMLSchema.new(coreData.mod.name .. "_" .. coreData.name .. "Map")
            end
            if coreData.xmlSchemaModSettings == nil then
                coreData.xmlSchemaModSettings = XMLSchema.new(coreData.mod.name .. "_" .. coreData.name .. "ModSettings")
            end
            if coreData.xmlSchemaSavegame == nil then
                coreData.xmlSchemaSavegame = XMLSchema.new(coreData.mod.name .. "_" .. coreData.name .. "Savegame")
            end
        end)
        xmlManager:addInitSchemaFunction(function()
            if coreData.xmlSchemaMap ~= nil then
                self:registerMapXMLPaths(coreData.xmlSchemaMap, coreData.xmlKey)
            end
            if coreData.xmlSchemaModSettings ~= nil then
                self:registerModSettingsXMLPaths(coreData.xmlSchemaModSettings, coreData.xmlKey)
            end
            if coreData.xmlSchemaSavegame ~= nil then
                self:registerSavegameXMLPaths(coreData.xmlSchemaSavegame, coreData.xmlKey)
            end
        end)
        self:initThirdPartyMods()
        THUtils.createDebugConsoleCommands(self.coreData.name, self)
        g_thEventManager:addEventListener(self)
        return self
    end
end
function THCore.registerMapXMLPaths(self, xmlSchema, xmlPath)
end
function THCore.registerModSettingsXMLPaths(self, xmlSchema, xmlPath)
end
function THCore.registerSavegameXMLPaths(self, xmlSchema, xmlPath)
end
function THCore.initThirdPartyMods(self)
    local thModData = g_thModManager:getActiveMod("FS25_precisionFarming")
    if thModData ~= nil then
        self.coreData.thirdPartyMods.precisionFarming = thModData
    end
end
function THCore.initModSettings(self)
    local modSettingsPath = g_modSettingsDirectory .. self.coreData.mod.name .. "/"
    createFolder(modSettingsPath)
    self.coreData.modSettingsPath = modSettingsPath
end
function THCore.onSetMissionInfo(self, mission, missionInfo, missionDynamicInfo)
    self.coreData.mission = mission
    self.coreData.missionInfo = missionInfo
    self.coreData.missionDynamicInfo = missionDynamicInfo
    self.coreData.isExistingSave = false
    local savegamePath = THUtils.getNormalizedFilePath(missionInfo.savegameDirectory)
    local totalPlayTime = missionInfo.playTime or 0
    if savegamePath ~= nil and savegamePath ~= "" then
        self.coreData.savegamePath = savegamePath
        if totalPlayTime > 0 then
            self.coreData.isExistingSave = true
        end
    end
end
function THCore.loadFromMapXML(self, xmlFile, xmlKey, customEnv, baseDirectory)
    customEnv = customEnv or self.coreData.mod.name
    baseDirectory = baseDirectory or self.coreData.mod.path
    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)
    then
        return true
    end
    return false
end
function THCore.onDelete(self)
    g_thEventManager:removeEventListener(self)
end
function THCore.getMapXMLFileParams(self, xmlKey, useMapSettings, forceMapSettings)
    local mapData = self.coreData.map
    if THUtils.argIsValid(xmlKey == nil or (type(xmlKey) == THValueType.STRING and xmlKey ~= ""), "xmlKey", xmlKey)
        and THUtils.argIsValid(not useMapSettings or useMapSettings == true, "useMapSettings", useMapSettings)
        and THUtils.argIsValid(not forceMapSettings or forceMapSettings == true, "forceMapSettings", forceMapSettings)
        and mapData ~= nil
    then
        local mapXMLFilename = nil
        local customEnv = nil
        local baseDirectory = nil
        local isMapSettings = false
        if useMapSettings then
            local mapSettingsData = self.coreData.mapSettings
            if mapSettingsData ~= nil and fileExists(mapSettingsData.xmlFilename) then
                local settingsXMLFile = XMLFile.load(self.coreData.name .. "MapSettingsXML", mapSettingsData.xmlFilename)
                local settingsXMLKey = mapSettingsData.xmlRootKey .. ".maps." .. mapData.name
                if settingsXMLFile ~= nil then
                    if settingsXMLFile:hasProperty(settingsXMLKey) then
                        mapXMLFilename = settingsXMLFile:getString(settingsXMLKey .. "#filename")
                        if mapXMLFilename ~= nil then
                            mapXMLFilename = THUtils.getFilename(mapXMLFilename, mapSettingsData.mod.path)
                            if mapXMLFilename ~= nil then
                                if fileExists(mapXMLFilename) then
                                    customEnv = mapSettingsData.mod.name
                                    baseDirectory = mapSettingsData.mod.path
                                    isMapSettings = true
                                else
                                    mapXMLFilename = nil
                                end
                            end
                        end
                    end
                    settingsXMLFile:delete()
                end
            end
        end
        if mapXMLFilename == nil and not forceMapSettings and mapData.isMod then
            mapXMLFilename = THUtils.getFilename(mapData.xmlFilename, mapData.path, true)
            if mapXMLFilename ~= nil then
                if fileExists(mapXMLFilename) then
                    customEnv = mapData.mod.name
                    baseDirectory = mapData.path
                else
                    mapXMLFilename = nil
                end
            end
        end
        if mapXMLFilename ~= nil then
            local dataXMLFilename = nil
            local dataXMLKey = "map"
            if xmlKey == nil then
                dataXMLFilename = mapXMLFilename
            else
                dataXMLKey = "map." .. xmlKey
                local mapXMLFile = XMLFile.load(self.coreData.name .. "MapXML", mapXMLFilename)
                if mapXMLFile ~= nil
                    and mapXMLFile:hasProperty(dataXMLKey)
                then
                    dataXMLFilename = mapXMLFile:getString(dataXMLKey .. "#filename")
                    if dataXMLFilename == nil then
                        dataXMLFilename = mapXMLFilename
                    else
                        dataXMLFilename = THUtils.getFilename(dataXMLFilename, baseDirectory)
                        if dataXMLFilename ~= nil then
                            if fileExists(dataXMLFilename) then
                                dataXMLKey = xmlKey
                            else
                                dataXMLFilename = nil
                            end
                        end
                    end
                    mapXMLFile:delete()
                end
            end
            if dataXMLFilename ~= nil then
                return dataXMLFilename, dataXMLKey, customEnv, baseDirectory, isMapSettings
            end
        end
    end
end
function THCore.loadMapData(self, xmlKey, useMapSettings, forceMapSettings)
    xmlKey = xmlKey or self.coreData.xmlKey
    useMapSettings = THUtils.getNoNil(useMapSettings, true)
    local dataXMLFilename, dataXMLKey, customEnv, baseDirectory = self:getMapXMLFileParams(xmlKey, useMapSettings, forceMapSettings)
    if dataXMLFilename ~= nil and dataXMLKey ~= nil then
        local dataXMLFile = XMLFile.load(self.coreData.mod.name .. "MapConfigXML", dataXMLFilename, self.coreData.xmlSchemaMap)
        if dataXMLFile ~= nil then
            THUtils.displayMsg(THMessage.LOADING, dataXMLFilename)
            g_thEventManager:raiseEvent("loadFromMapXML", dataXMLFile, dataXMLKey, customEnv, baseDirectory)
            dataXMLFile:delete()
        end
    end
end
function THCore.loadModSettings(self, xmlFilename, xmlKey)
    xmlFilename = xmlFilename or self.coreData.name .. ".xml"
    xmlKey = xmlKey or self.coreData.xmlKey
    if THUtils.argIsValid(type(xmlFilename) == THValueType.STRING and xmlFilename ~= "", "xmlFilename", xmlFilename)
        and THUtils.argIsValid(type(xmlKey) == THValueType.STRING and xmlKey ~= "", "xmlKey", xmlKey)
        and self.coreData.modSettingsPath ~= nil
    then
        local absXMLFilename = THUtils.getFilename(xmlFilename, self.coreData.modSettingsPath)
        if absXMLFilename ~= nil then
            local xmlFile = nil
            local isXMLFileNew = false
            if fileExists(absXMLFilename) then
                xmlFile = XMLFile.load(self.coreData.mod.name .. "_ModSettingsConfigXML", absXMLFilename, self.coreData.xmlSchemaModSettings)
            else
                xmlFile = XMLFile.create(self.coreData.mod.name .. "_ModSettingsConfigXML", absXMLFilename, xmlKey, self.coreData.xmlSchemaModSettings)
                isXMLFileNew = true
            end
            if xmlFile ~= nil then
                g_thEventManager:raiseEvent("loadFromModSettingsXML", xmlFile, xmlKey, isXMLFileNew)
                if isXMLFileNew then
                    xmlFile:save()
                end
                xmlFile:delete()
            end
        end
    end
end
function THCore.createInfoLayer(self, name, size, numChannels, basePath, isSaved, isSynced)
    if g_thDensityMapManager ~= nil then
        if type(name) == THValueType.STRING then
            name = self.coreData.name .. "_" .. name
        end
        return g_thDensityMapManager:createInfoLayer(name, size, numChannels, basePath, isSaved, isSynced)
    end
end
function THCore.getInfoLayer(self, infoLayerId, verbose)
    if g_thDensityMapManager ~= nil then
        if type(infoLayerId) == THValueType.STRING then
            if not string.find(infoLayerId, self.coreData.name, nil, true) then
                infoLayerId = self.coreData.name .. "_" .. infoLayerId
            end
        end
        return g_thDensityMapManager:getInfoLayer(infoLayerId, verbose)
    end
end