HDBuildingUpgradeEvent = {}
local HDBuildingUpgradeEvent_mt = Class(HDBuildingUpgradeEvent, Event)
InitEventClass(HDBuildingUpgradeEvent, "HDBuildingUpgradeEvent")

function HDBuildingUpgradeEvent.emptyNew()
    return Event.new(HDBuildingUpgradeEvent_mt)
end

function HDBuildingUpgradeEvent.new(placeable, level, isRequest, showNotification)
    local self = HDBuildingUpgradeEvent.emptyNew()
    self.placeable = placeable
    self.level = level or 1
    self.isRequest = isRequest == true
    self.showNotification = showNotification ~= false
    return self
end

function HDBuildingUpgradeEvent:writeStream(streamId, connection)
    NetworkUtil.writeNodeObject(streamId, self.placeable)
    streamWriteBool(streamId, self.isRequest)
    streamWriteBool(streamId, self.showNotification)
    streamWriteUIntN(streamId, self.level, 5)
end

function HDBuildingUpgradeEvent:readStream(streamId, connection)
    self.placeable = NetworkUtil.readNodeObject(streamId)
    self.isRequest = streamReadBool(streamId)
    self.showNotification = streamReadBool(streamId)
    self.level = streamReadUIntN(streamId, 5)
    self:run(connection)
end

function HDBuildingUpgradeEvent:run(connection)
    if self.placeable == nil then
        return
    end

    if self.isRequest then
        if g_server == nil then
            return
        end
        local farmId = g_currentMission:getFarmId(connection)
        if farmId == nil then
            Logging.warning("[HD Building Upgrades] Upgrade request rejected: no farm for connection")
            return
        end
        local spec = HDPlaceableUpgrade.ensureRuntimeSpec(self.placeable)
        HDUpgradeSavegame.applyPendingLevel(self.placeable)
        Logging.info(
            "[HD Building Upgrades] Upgrade request: building=%s level=%s maxLevel=%s farmId=%s ownerFarmId=%s",
            self.placeable:getName(),
            tostring(spec ~= nil and spec.level or 1),
            tostring(HDPlaceableUpgrade.getMaxLevel(self.placeable)),
            tostring(farmId),
            tostring(self.placeable:getOwnerFarmId())
        )
        local success, errorText = HDPlaceableUpgrade.upgrade(self.placeable, farmId)
        if success then
            local spec = self.placeable[HDPlaceableUpgrade.SPEC_TABLE_NAME]
            Logging.info(
                "[HD Building Upgrades] Upgrade successful: building=%s level=%d",
                self.placeable:getName(),
                spec.level
            )
            g_server:broadcastEvent(HDBuildingUpgradeEvent.new(self.placeable, spec.level, false, true), false)
            if g_currentMission ~= nil then
                g_currentMission:addIngameNotification(FSBaseMission.INGAME_NOTIFICATION_INFO, string.format(g_i18n:getText("hd_upgrade_done"), self.placeable:getName(), spec.level))
            end
        elseif g_currentMission ~= nil then
            Logging.warning(
                "[HD Building Upgrades] Upgrade rejected: building=%s reason=%s",
                self.placeable:getName(),
                tostring(errorText)
            )
            g_currentMission:addIngameNotification(FSBaseMission.INGAME_NOTIFICATION_CRITICAL, g_i18n:getText(errorText))

            local spec = self.placeable[HDPlaceableUpgrade.SPEC_TABLE_NAME]
            if connection ~= nil and spec ~= nil then
                connection:sendEvent(HDBuildingUpgradeEvent.new(self.placeable, spec.level, false, false))
            end
        end
    else
        HDPlaceableUpgrade.applyLevel(self.placeable, self.level)
        HDManagementDialog.refresh(self.placeable)
        if self.showNotification and g_currentMission ~= nil then
            local name = self.placeable.getName ~= nil and self.placeable:getName() or "Gebaeude"
            g_currentMission:addIngameNotification(
                FSBaseMission.INGAME_NOTIFICATION_INFO,
                string.format(g_i18n:getText("hd_upgrade_done"), name, self.level)
            )
        end

        if g_inGameMenu ~= nil
            and g_inGameMenu.pageProduction ~= nil
            and g_inGameMenu.pageProduction.updateMenuButtons ~= nil then
            local page = g_inGameMenu.pageProduction
            if page.updateProductionLists ~= nil then
                page:updateProductionLists()
            end
            page:updateMenuButtons()
        end
    end
end

function HDBuildingUpgradeEvent.sendRequest(placeable)
    if g_server ~= nil then
        local farmId = g_localPlayer ~= nil and g_localPlayer.farmId or 0
        local success, errorText = HDPlaceableUpgrade.upgrade(placeable, farmId)
        if success then
            local spec = placeable[HDPlaceableUpgrade.SPEC_TABLE_NAME]
            g_server:broadcastEvent(HDBuildingUpgradeEvent.new(placeable, spec.level, false), false)
            HDManagementDialog.refresh(placeable)
            g_currentMission:addIngameNotification(FSBaseMission.INGAME_NOTIFICATION_INFO, string.format(g_i18n:getText("hd_upgrade_done"), placeable:getName(), spec.level))
        else
            g_currentMission:addIngameNotification(FSBaseMission.INGAME_NOTIFICATION_CRITICAL, g_i18n:getText(errorText))
        end
    elseif g_client ~= nil then
        g_client:getServerConnection():sendEvent(HDBuildingUpgradeEvent.new(placeable, 1, true, false))
    end
end
