--------------------------------------------------------------
-- Includes
--------------------------------------------------------------
require('ai/L_ACTIVITY_MANAGER')

--//////////////////////////////////////////////////////////////////////////////////
-- User Config local variables
local waveTime = 5                             -- how often to spawn a new wave of mobs
local rewardInterval = 5                        -- how many waves to wait to drop a reward and give the player a coolDownTime
local coolDownTime = 10                         -- how long to wait between waves of rewardInterval
local startTier2Waves = 6                       -- wave number to start spawning tier 2 mobs
local startTier3Waves = 12                      -- wave number to start spawning tier 3 mobs
local displayCoolDown = false

-- Spawn Networks 
local spawnerNetworks = {
--**********************************tier1
    {spawnerName = 'hordespawner',        -- name of the tier 1 spawner network without the #'s from HF
    spawnerNum = 2,
    lastRand = 0}
}

-- Reward Networks
local rewardNetworks = {
--********************************Reward1
    {spawnerName = 'Rewards_',              -- name of the reward 1 spawner network without the #'s from HF
    spawnerNum = 2,
    lastRand = 0},} 
--***************************************

-- Script only local variables
local timerTick = 0         -- tick variable
local coolDownTick = 10     -- cool down tick variable
local waveNum = 1           -- current wave number
local rewardTick = 1        -- number of rewards given
local tPlayers = {}
local totalSpawned = 0
--//////////////////////////////////////////////////////////////////////////////////

----------------------------------------------------------------
-- Startup of the object
----------------------------------------------------------------.
function onStartup(self)     
    -- Initialize the pseudo random number generator and return 
    --self:SetVar('isCoolDown', false)  
    math.randomseed( os.time() )
    self:SetVar('playersAccepted', 0)
    self:SetVar('playersReady', false)
end

function onPlayerLoaded(self, msg)
    table.insert(tPlayers, msg.playerID:GetID())
    msg.playerID:SetUserCtrlCompPause{bPaused = true}
    
    self:NotifyClientZoneObject{name = 'Reset_Timer'}
	self:Help{rerouteID = msg.playerID, iHelpID = 0}
    playerLocationTransfer(self)
end

function onPlayerExit(self, msg)
    local playerNum = 0
    for i = 1, table.maxn(tPlayers) do
        if tPlayers[i] == msg.playerID:GetID() then
            playerNum = i
        end
    end
    
    if playerNum ~= 0 then
        table.remove(tPlayers, playerNum)
    end
end

function onFireEventServerSide(self, msg)   
    if msg.args == 'start' then
        --print('start')
        PlayerAccepted(self)
    elseif msg.args == 'exit' then        
        --print('exit')
        for k,v in ipairs(tPlayers) do
            GAMEOBJ:GetObjectByID(v):TransferToZone{ zoneID = 22, pos_x = 125, pos_y = 376, pos_z = -175  } --, rot_x = 0, rot_y = 0, rot_z = 0, rot_w = 0
        end
    end
end

function onFireEvent(self,msg)   
    if msg.args == 'start' then
        StartWaves(self)  
    elseif msg.args == 'front' and self:GetVar('playersReady') then
        playerLocationTransfer(self)
    elseif msg.args == 'back' then
        playerLocationTransfer(self, true)
    end
end

function onPlayerDied(self, msg)
    --print('player died ***********')
    GameOver(self, msg.playerID)
end

function onNotifyObject(self, msg)
    local player = msg.ObjIDSender
    --if not IsPlayerInActivity(player) then return end
    --print('Scored - ' .. msg.name .. ' - ' .. msg.param1)
    -- If the Quickbuild is done    
    if (msg.name == "built") then
       
        local hordeSpawner = LEVEL:GetSpawnerByName("hordespawner")
		if hordeSpawner then
			hordeSpawner:SpawnerActivate()
		end
    end
    
    if (msg.name == "qbdead") then
        local hordeSpawner = LEVEL:GetSpawnerByName("hordespawner")
		if hordeSpawner then
			hordeSpawner:SpawnerDeactivate()
		end
    end
    
    -- update smash count
    UpdateActivityValue(player, 1, 1)    
    -- update kill score
    UpdateActivityValue(player, 2, msg.param1)     
end

function playerLocationTransfer(self, bToBack)
    local playerCount = self:GetVar('playerCountFront')
    
    if not playerCount then 
        playerCount = 1
        self:SetVar('spawnFrontOnly', true)
        print('firstTime')
        print('# of players: ' .. playerCount)
        self:SetVar('playerCountFront', playerCount)
        return
    end
         
    if bToBack and playerCount > 0 then        
        playerCount = playerCount - 1   
        self:SetVar('playerCountFront', playerCount)
        
        if playerCount == 0 then
            print('reset spawns to back ** spawnBackOnly ' .. playerCount)
            self:SetVar('spawnBackOnly', true)
            self:SetVar('spawnFrontOnly', false)
        end
    elseif not bToBack and playerCount < table.maxn(tPlayers) then
        playerCount = playerCount + 1 
        self:SetVar('playerCountFront', playerCount)
        print('# of players in front' .. playerCount)
        
        if playerCount == table.maxn(tPlayers) and not bToBack then
            print('reset spawns to front ** spawnFrontOnly ' .. playerCount)
            self:SetVar('spawnFrontOnly', true)
            self:SetVar('spawnBackOnly', false)
        end
    end
    
    if playerCount > 0 and playerCount < table.maxn(tPlayers) then
        print('spawnBoth ' .. playerCount)   
        self:SetVar('spawnFrontOnly', false)
        self:SetVar('spawnBackOnly', false)
    else        
        --spawnMobs(self) 
    end
    
    print('# of players in table: ' .. tostring(table.maxn(tPlayers)) .. ' players in front: ' .. playerCount)    
end

function PlayerAccepted(self)
    self:SetVar('playersAccepted', self:GetVar('playersAccepted') + 1)
    
    if self:GetVar('playersAccepted') >= table.maxn(tPlayers) then
        print('All players have accepted')
        StartWaves(self)  
    end
end
function StartWaves(self)    
    SetupActivity(4)    
    self:SetVar('playersReady', true)
    self:SetVar('playersAccepted', 0)
    for k,v in ipairs(tPlayers) do
        UpdatePlayer(GAMEOBJ:GetObjectByID(v))        
        GAMEOBJ:GetObjectByID(v):SetUserCtrlCompPause{bPaused = false}
        GetLeaderboardData(self, GAMEOBJ:GetObjectByID(v), 5)
        -- start the music
        GAMEOBJ:GetObjectByID(v):ActivateNDAudioMusicCue{m_NDAudioMusicCueName = 'AG_Horde'}
        -- set music to cooldown the music
        --GAMEOBJ:GetObjectByID(v):SetNDAudioMusicParameter{m_NDAudioMusicParameterName = 'Intensity', m_Value = 3.0}
    end
    
    --self:NotifyClientZoneObject{name = 'Start_Timer', param1 = timerTick}
    self:SetVar('wavesStarted', true)
    if displayCoolDown then            
        GAMEOBJ:GetTimer():AddTimerWithCancel(1, "CoolDownTick", self )
    else       
        self:NotifyClientZoneObject{name = 'Start_Wave_Message', paramStr = "Start!"}
        GAMEOBJ:GetTimer():AddTimerWithCancel(3, "StartDelay", self )
    end
end

-- exit
function GameOver(self, player)  
    GAMEOBJ:GetTimer():CancelAllTimers(self) 
    KillMobs(self)
    for k,v in ipairs(tPlayers) do   
        local smashVar = GetActivityValue(GAMEOBJ:GetObjectByID(v), 2)--/totalSpawned
        local scoreVar = GetActivityValue(GAMEOBJ:GetObjectByID(v), 1)
 --       StopActivity(GAMEOBJ:GetObjectByID(v), timerTick, smashVar, scoreVar)
        --print('smashed = ' .. GetActivityValue(GAMEOBJ:GetObjectByID(v), 2) .. ' out of ' .. totalSpawned .. ' for ' .. smashVar .. ' score = ' .. scoreVar)
        -- stop the music
        GAMEOBJ:GetObjectByID(v):DeactivateNDAudioMusicCue{m_NDAudioMusicCueName = 'AG_Horde'}
    end
    
    -- reset ticks
    timerTick = 0                   -- tick variable
    coolDownTick = coolDownTime     -- cool down tick variable
    waveNum = 1                     -- current wave number
    rewardTick = 1                  -- number of rewards given    
    self:SetVar('wavesStarted', false)
end

function newRand(oldNum, maxRand)
    if maxRand == 1 then
        return '01', '01'
    end
    
    local randNum = math.random(1, maxRand)
    
    if randNum < 10 then
        randNum = '0' .. randNum
    end
        
    while randNum == oldNum do
        --print('found same')
        randNum = math.random(1, maxRand)
        
        if randNum < 10 then
            randNum = '0' .. randNum
        end
    end
    
    return randNum, randNum
end

function spawnerResetT(spawnNetwork, bMaintainSpawnNum)
    for k,v in ipairs(spawnNetwork) do 
        for i = 1, v.spawnerNum do 
            --print('kill: ' .. v.spawnerName .. '0' .. i)
            local spawner = LEVEL:GetSpawnerByName(v.spawnerName .. '0' .. i)
            if spawner then
                --track total mobs spawned
                totalSpawned = totalSpawned + spawner:SpawnerGetTotalSpawned().iSpawned
                
                if not bMaintainSpawnNum then
                    spawner:SpawnerDestroyObjects()
                    spawner:SpawnerSetNumToMaintain{uiNum = 1}
                end
                spawner:SpawnerDeactivate()
            end
        end
    end
end



function KillMobs(self)
    --print('Kill Mobs ***')
    spawnerResetT(spawnerNetworks)
    spawnerResetT(rewardNetworks)
end
--[[
function spawnMobs(self)        
    if not self:GetVar('wavesStarted') then return end
    
    local spawnNum = waveNum
    if spawnNum > rewardInterval then
        spawnNum = spawnNum - (rewardTick-1)
    end
       
    updateSpawner(self, spawnerNetworks[1], spawnNum)
    
    if waveNum >= startTier2Waves and spawnNum - startTier2Waves > 0 then
        updateSpawner(self, spawnerNetworks[2], spawnNum - startTier2Waves)
    end
    if waveNum >= startTier3Waves and spawnNum - startTier3Waves > 0 then
        updateSpawner(self, spawnerNetworks[3], spawnNum - startTier3Waves)
    end
end
--]]
--[[
function waveReward(self)
    --print('Cool Down')
    updateSpawner(self, rewardNetworks[1], 1)
    rewardTick = rewardTick + 1
end
--]]

function onPlayerResurrected(self, msg)
    --print('resurrected')      
    self:NotifyClientZoneObject{name = 'Reset_Timer'}
    
    for i = 1, table.maxn(tPlayers) do
        self:Help{rerouteID = GAMEOBJ:GetObjectByID(tPlayers[i]), iHelpID = 0}
    end
end

-- timers...
function onTimerDone(self, msg)
    if msg.name == "StartDelay" then        
        GAMEOBJ:GetTimer():AddTimerWithCancel(1, "ClockTick", self )
    end
    
    if msg.name == "ClockTick" then
        timerTick = timerTick + 1
        --print('Wave: ' .. waveNum .. ' Tick: ' .. timerTick .. ' : ' .. ((waveTime * (waveNum-1)) + (coolDownTime * (rewardTick-1))))
                
        if timerTick >= ((waveTime * (waveNum-1)) + (coolDownTime * (rewardTick-1))) or timerTick == 1 then    
           -- spawnMobs(self)
            --print('spawn number: ' .. waveNum .. ' @ ' .. timerTick)          
            
            if waveNum == rewardInterval * rewardTick then     
                -- set music to cooldown the music
                for k,v in ipairs(tPlayers) do
                    GAMEOBJ:GetObjectByID(v):SetNDAudioMusicParameter{m_NDAudioMusicParameterName = 'Intensity', m_Value = 0.0}
                end               
                
               -- waveReward(self)
                --print('stopping clock tick')
                GAMEOBJ:GetTimer():CancelTimer( "ClockTick", self )                
                GAMEOBJ:GetTimer():AddTimerWithCancel(1, "CoolDownTick", self )
                spawnerResetT(spawnerNetworks, true)     
                --waveNum = waveNum + 1      
                return      
            end
            
            waveNum = waveNum + 1 
        end
        --print('clock tick starting clock tick')
        GAMEOBJ:GetTimer():AddTimerWithCancel(1, "ClockTick", self )
        self:NotifyClientZoneObject{name = 'Update_Timer', param1 = timerTick}
    end    
    
    if msg.name == "CoolDownTick" then          
        --print('cooldown ' .. coolDownTick)
        coolDownTick = coolDownTick - 1        
 
        if not displayCoolDown then   
            timerTick = timerTick + 1
            self:NotifyClientZoneObject{name = 'Update_Timer', param1 = timerTick}
        end
        
        if coolDownTick <= 1 then      
            --self:SetVar('isCoolDown', false)  
            --print('cool down starting clock tick')
            GAMEOBJ:GetTimer():AddTimerWithCancel(1, "ClockTick", self )
                        
            coolDownTick = coolDownTime 
            
            local iValue = 1.0
            if rewardTick == 2 then
                iValue = 2.0
            elseif rewardTick > 2 then
                iValue = 3.0
            end
            
            -- set music to cooldown the music
            for k,v in ipairs(tPlayers) do
                GAMEOBJ:GetObjectByID(v):SetNDAudioMusicParameter{m_NDAudioMusicParameterName = 'Intensity', m_Value = iValue}
            end
            
            return
        end
                            
        GAMEOBJ:GetTimer():AddTimerWithCancel(1, "CoolDownTick", self )
        if displayCoolDown then
            if coolDownTick > coolDownTime/2  and coolDownTick > 0 then
                self:NotifyClientZoneObject{name = 'Wave_Message', paramStr = rewardTick}
            elseif coolDownTick == 0 then        
                self:NotifyClientZoneObject{name = 'Start_Wave_Message', paramStr = "Start!"}
            else
                self:NotifyClientZoneObject{name = 'Update_Timer', param1 = coolDownTick}
            end
        end
    end
end