-- Lampovo Project ^ω^ Average Enjoyer

loadBales = {}

local modDir = g_currentModDirectory
local modName = g_currentModName

function loadBales.loadMapData(self, superFunc, xmlFile, missionInfo, baseDirectory)
    superFunc(self, xmlFile, missionInfo, baseDirectory)
    local xmlFilename = Utils.getFilename('xml/bales.xml', modDir)

    if xmlFilename == nil then
        Logging.xmlInfo(xmlFile, "No bales xml defined in mod")

        return false
    end

    local balesXMLFile = XMLFile.load("TempBales", xmlFilename, BaleManager.mapBalesXMLSchema)

    if balesXMLFile ~= nil then
        g_baleManager:loadBales(balesXMLFile, modDir)
        balesXMLFile:delete()
    end

    return true
end

BaleManager.loadMapData = Utils.overwrittenFunction(BaleManager.loadMapData, loadBales.loadMapData)

local testBales = false

function loadBales.consoleCommandAddBaleAll(self, superFunc, drawSizeBox)
    if g_server == nil then
        Logging.error("Command only allowed on server!")
        return
    end

    drawSizeBox = string.lower(drawSizeBox or "") == "true"

    local wx, wy, wz
    local dirX, dirZ
    if self.debugLoadPosition == nil then
        wx, wy, wz = g_localPlayer:getPosition()
        dirX, dirZ = g_localPlayer:getCurrentFacingDirection()
        self.debugLoadPosition = {wx, wy, wz, dirX, dirZ}
    else
        wx, wy, wz = self.debugLoadPosition[1], self.debugLoadPosition[2], self.debugLoadPosition[3]
        dirX, dirZ = self.debugLoadPosition[4], self.debugLoadPosition[5]
    end

    if self.debugBales ~= nil then
        for _, bale in ipairs(self.debugBales) do
            bale:delete()
        end
    end

    g_debugManager:removeGroup("baleManager")

    self.debugBales = {}

    self:unloadBaleData()
    g_i3DManager:clearEntireSharedI3DFileCache()
    self.bales = {}

    local xmlFilename = Utils.getFilename('xml/bales.xml', modDir)
    local balesXMLFile = XMLFile.load("TempBales", xmlFilename, BaleManager.mapBalesXMLSchema)
    if balesXMLFile ~= nil then
        self:loadBales(balesXMLFile, modDir)
        balesXMLFile:delete()
    end

    local function spawnBales()
        local boxColor = Color.new(0.2, 0.2, 0.2, 1)

        wx, wz = wx + dirX * 4, wz + dirZ * 4
        local yRot = MathUtil.getYRotationFromDirection(dirX, dirZ)

        local xOffset, zOffset = 0, 0
        for baleIndex, bale in ipairs(self.bales) do
            for _, fillTypeData in ipairs(bale.fillTypes) do
                zOffset = (bale.isRoundbale and bale.width or bale.length) * 0.5
                for variationIndex, variationData in ipairs(bale.variations) do
                    local x, z = wx + dirX * zOffset - dirZ * xOffset, wz + dirZ * zOffset + dirX * xOffset

                    local baleHeight = (bale.isRoundbale and bale.diameter or bale.height)
                    local y = getTerrainHeightAtWorldPos(g_terrainNode, x, 0, z) + baleHeight * 0.5 + 0.25

                    local baleObject = Bale.new(g_currentMission:getIsServer(), g_currentMission:getIsClient())
                    if baleObject:loadFromConfigXML(bale.xmlFilename, x, y, z, 0, yRot, 0) then
                        baleObject:setFillType(fillTypeData.fillTypeIndex, true)
                        baleObject:setVariationIndex(variationIndex)
                        baleObject:setOwnerFarmId(g_currentMission:getFarmId(), true)
                        baleObject:register()
                        baleObject:removeFromPhysics()

                        local debugString = string.format("%s (%s - %s)", Utils.getFilenameFromPath(bale.xmlFilename), g_fillTypeManager:getFillTypeNameByIndex(fillTypeData.fillTypeIndex), variationData.id)

                        local rx, ry, rz = localRotationToWorld(baleObject.nodeId, 0, math.pi, 0)
                        DebugText3D.new():createWithWorldPos(x, y + baleHeight * 0.5 + 0.25, z, rx, ry, rz, debugString, 0.07):addToManager("baleManager", nil, math.huge)

                        if drawSizeBox then
                            local sizeX, sizeY, sizeZ
                            if bale.isRoundbale then
                                sizeX, sizeY, sizeZ = bale.diameter, bale.diameter, bale.width
                            else
                                sizeX, sizeY, sizeZ = bale.width, bale.height, bale.length
                            end
                            DebugBox.new():createWithWorldPosAndRot(x, y, z, rx, ry, rz, sizeX, sizeY, sizeZ):setColor(boxColor):addToManager("baleManager", nil, math.huge)
                        end

                        table.insert(self.debugBales, baleObject)
                    end

                    zOffset = zOffset + (bale.isRoundbale and bale.width or bale.length) + 0.2
                end

                xOffset = xOffset + 0.5
            end

            xOffset = xOffset + 2.5
        end
    end

    local numBalesToLoad = #self.bales
    local function baleLoaded(_self, i3dNode, failedReason, bale)
        _self.baleLoaded(i3dNode, failedReason, bale)
        numBalesToLoad = numBalesToLoad - 1
        if numBalesToLoad == 0 then
            spawnBales()
        end
    end

    for _, bale in ipairs(self.bales) do
        bale.sharedLoadRequestId = g_i3DManager:loadSharedI3DFileAsync(bale.i3dFilename, false, true, baleLoaded, self, bale)
    end
end

if testBales then
    BaleManager.consoleCommandAddBaleAll = Utils.overwrittenFunction(BaleManager.consoleCommandAddBaleAll, loadBales.consoleCommandAddBaleAll)
end