local class = require("class")
include("util.lua")

DeathRollManager = class()

function DeathRollManager:init(script, ship, options)
    self.script = script
    self.options = options

    self.ship = ship

    self.maximumTime = self.ship:getTimeUntilExplosion()

    self.numberStack = 0

    self.lastGlowFlickerTime = -1;

    self:rebuildAliveTable()

    self.subsysPerSecond = -1
end

function DeathRollManager:rebuildAliveTable()
    self.aliveTable = {}

    self.subsysNumber = #self.ship

    for i = 1, self.subsysNumber do
        local subsys = self.ship[i]
        if (subsys.HitpointsLeft > 0 and self:isValidSubsystem(subsys)) then
            table.insert(self.aliveTable, i)
        end
    end
end

function DeathRollManager:getOption(key, default)
    if (self.options) then
        local val = self.options[key]

        if (val == nil) then
            return default
        else
            return val
        end
    else
        return default
    end
end

function DeathRollManager:hasOption(key)
    return self:getOption(key) ~= nil
end

function DeathRollManager:isValidSubsystem(subsystem)
    if (not subsystem:isValid()) then
        return false
    end

    if (self:getOption("noTurrets", false)) then
        if (subsystem:isTurret()) then
            return false
        end
    end

    return true
end

function DeathRollManager:findRandomAliveSubsystem()
    local subsys
    local index

    if (#self.aliveTable == 0) then
        return nil
    end

    index = safeRand(1, #self.aliveTable, true)

    subsys = self.ship[self.aliveTable[index]]

    return index, subsys
end

function DeathRollManager:shouldDoSubsystemBlowup()
    local shipTime = self.ship:getTimeUntilExplosion()
    local elapsedTime = self.maximumTime - shipTime

    if (elapsedTime < self:getOption("subsysDelay", 0)) then
        return false
    end

    local current = shipTime - self:getOption("subsysDelay", 0) - self:getOption("subsysEarlyEnd", 0)

    if (current < 0) then
        return false
    end

    return true, current
end

function DeathRollManager:blowUpSubsystems(time)
    local bool, time = self:shouldDoSubsystemBlowup()

    if (bool) then
        if (self.lastTime == nil) then
            self.subsysPerSecond = self.subsysNumber / time

            self.lastTime = time
            return
        end

        local difference = self.lastTime - time

        self.lastTime = time

        if (difference <= 0) then
            return
        end

        local num = difference * self.subsysPerSecond + self.numberStack
        self.numberStack = num

        for i = 1, num do
            local index, subsys = self:findRandomAliveSubsystem()

            if (index ~= nil) then
                self:destroySubsystem(index, subsys)
            end

            self.numberStack = self.numberStack - 1
        end
    end
end

function DeathRollManager:destroySubsystem(index, subsys)
    if (subsys.HitpointsLeft <= 0) then
        return
    end

    subsys.HitpointsLeft = -1

    for i, v in ipairs(self.aliveTable) do
        if (v == index) then
            table.remove(self.aliveTable, i)
            break
        end
    end
end

function DeathRollManager:shouldDoFlicker(time)
    if (self.lastGlowFlickerTime == -1) then
        return true
    end

    local diff = mn.getMissionTime() - self.lastGlowFlickerTime
    local delay = self:getOption("flickerDelay", 0.1)

    if (diff >= delay * safeRand(0.9, 1.1)) then
        return true
    end

    return false
end

function DeathRollManager:doGlowFlicker(time)
    if (self:shouldDoFlicker(time)) then
        local progress = 1 - (self.ship:getTimeUntilExplosion() / self.maximumTime)

        local showGlowMap = math.random() > progress
        local showGlowPoints = math.random() > progress

        local glowMapSEXP

        if (showGlowMap) then
            glowMapSEXP = "activate-glow-maps"
        else
            glowMapSEXP = "deactivate-glow-maps"
        end

        local glowPointSEXP

        if (showGlowMap) then
            glowPointSEXP = "activate-glow-points"
        else
            glowPointSEXP = "deactivate-glow-points"
        end

        mn.runSEXP(string.format("( %q %q )", glowMapSEXP, self.ship.Name))
        mn.runSEXP(string.format("( %q %q )", glowPointSEXP, self.ship.Name))

        self.lastGlowFlickerTime = mn.getMissionTime()
    end
end

function DeathRollManager:update(time)
    self:blowUpSubsystems(time)

    self:doGlowFlicker(time)
end

function DeathRollManager:isValid()
    if (self.ship == nil or not self.ship:isValid()) then
        return false
    end

    if (self.ship:getTimeUntilExplosion() < 0) then
        return false
    end

    return true
end
