require "TimedActions/ISBaseTimedAction"

-- Optional visual helper (will no-op if not present)
pcall(function() require "MSW_Visual" end)

MSW_ISLaunchVehicle = ISBaseTimedAction:derive("MSW_ISLaunchVehicle")

local TARGET_PART_ID = "ATAMultiSlotWrecker"

local function msw_applyVisual(trailer, forceVisible)
    if not trailer then return end
    local part = trailer:getPartById(TARGET_PART_ID)
    if not part then return end

    -- Prefer the visual helper (keeps logic in one place)
    if MSW_Visual and MSW_Visual.applyForVehicle then
        pcall(function() MSW_Visual.applyForVehicle(trailer) end)
        return
    end

    -- Fallback: simple toggle of the "Default" model
    if forceVisible ~= nil then
        pcall(function() part:setModelVisible("Default", forceVisible) end)
    end
end

local function msw_countOccupiedSlots(part)
    if not part then return 0 end
    local md = part:getModData()
    local slots = md and md.msw and md.msw.slots or nil
    if type(slots) ~= "table" then return 0 end
    local c = 0
    for _, v in pairs(slots) do
        if v then c = c + 1 end
    end
    return c
end

local function msw_refreshSoon(trailer, ticks)
    ticks = ticks or 10 -- ~0.3s
    local function onTick()
        ticks = ticks - 1
        if ticks <= 0 then
            msw_applyVisual(trailer, nil) -- pull latest modData-based state
            Events.OnTick.Remove(onTick)
        end
    end
    Events.OnTick.Add(onTick)
end

function MSW_ISLaunchVehicle:isValid()
    return self.trailer and not self.trailer:isRemovedFromWorld()
end

function MSW_ISLaunchVehicle:update()
    self.character:faceThisObject(self.trailer)
    self.character:setMetabolicTarget(Metabolics.HeavyWork)
end

function MSW_ISLaunchVehicle:start()
    setGameSpeed(1)
    self:setActionAnim("Loot")
    self.trailer:getEmitter():playSound("ATAVehicleWrecker")
end

function MSW_ISLaunchVehicle:stop()
    self.trailer:getEmitter():stopSoundByName("ATAVehicleWrecker")
    ISBaseTimedAction.stop(self)
end

function MSW_ISLaunchVehicle:perform()
    -- Before we send the command, estimate whether the model should remain visible after unload
    local part = self.trailer and self.trailer:getPartById(TARGET_PART_ID) or nil
    local occupied = msw_countOccupiedSlots(part)
    local expectedAfter = math.max(0, occupied - 1)
    local remainVisible = expectedAfter > 0

    sendClientCommand(self.character, 'msw', 'launchVehicle', {
        trailer = self.trailer:getId(),
        x = self.square:getX(),
        y = self.square:getY(),
        slot = self.slotIndex
    })

    -- Tiny refresh: optimistically toggle based on expected slot count after unload
    msw_applyVisual(self.trailer, remainVisible)
    -- And refresh again shortly after server syncs modData down
    msw_refreshSoon(self.trailer, 12)

    setGameSpeed(1)
    self.trailer:getEmitter():stopSoundByName("ATAVehicleWrecker")
    ISBaseTimedAction.perform(self)
end

function MSW_ISLaunchVehicle:new(character, trailer, sq, slotIndex)
    local o = {}
    setmetatable(o, self)
    self.__index = self
    o.character = character
    o.trailer = trailer
    o.square = sq
    o.slotIndex = slotIndex
    o.isFadeOut = false
    o.maxTime = 330
    if character:isTimedActionInstant() then o.maxTime = 10 end
    return o
end