
-- 13925 Castle Corner Inner 2 9499 3 4210
-- 13926 Castle Gate 2 9503 3 4214
-- 13927 Castle Tower 2 9507 3 4218
-- 13928 Castle Wall Bridge 2 9508 3 4219
-- 13929 Castle Wall Straight 2 9514 3 4225
-- 13930 Castle Wall T 2 9517 3 4228
-- 13931 Castle Wall Tower With Top
-- 13932 Castle Wall Widening 2 9520 3 4231

-- 14202 Castle Wall Tower With Top QB
-- 14206 Castle Corner Inner QB
-- 14207 Castle Gate QB
-- 14208 Castle Tower QB
-- 14209 Castle Wall Bridge QB
-- 14210 Castle Wall Straight QB
-- 14211 Castle Wall T QB
-- 14213 Castle Wall Widening QB

-- 16131 Center Object



--------------------------------------------------------------
-- Generic Survival Instance Client Zone Script: Including this 
-- file gives the custom functions for the Survival game.
-- updated mrb... 12/8/10 - updates for UI bugs
--------------------------------------------------------------

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

--//////////////////////////////////////////////////////////////////////////////////
-- local variables
local teamScoreBoard = {}
local tMedalsSolo = {   {name = Localize("Missions_467_name"), score  = 300},   -- 467; Survivor
                        {name = Localize("Missions_468_name"), score = 600} }   -- 468; Ultimate Survivor
local tMedals = {   {name = Localize("Missions_392_name"), score = 60},         -- 392; Outwit
                    {name = Localize("Missions_393_name"), score = 180},        -- 393; Outplay
                    {name = Localize("Missions_394_name"), score = 300},        -- 394; Outlast
                    {name = Localize("Missions_395_name"), score = 420},        -- 395; Survivalist
                    {name = Localize("Missions_396_name"), score = 480},        -- 396; Be Prepared!
                    {name = Localize("Missions_397_name"), score = 540},        -- 397; Paramedics!
                    {name = Localize("Missions_398_name"), score = 600},   }    -- 398; Unstoppable!
                    
                    
local bFirstTime = true
local checkMission = 479 	-- earn your sentinel badge
local checkMissionTime = 60	-- earn your sentinel badge time
---------------------------------------------------------------
-- Startup of the object
---------------------------------------------------------------

function string.starts(String,Start)
   return string.sub(String,1,string.len(Start))==Start
end


function playerInit(self)
	print("PLAYER INIT")
    local player = GAMEOBJ:GetObjectByID(GAMEOBJ:GetLocalCharID())
    
    UI:SendMessage( "pushGameState", {{"state", "Survival"}})
    -- set player to auto-respawn
    --player:SetPlayerAllowedRespawn{dontPromptForRespawn=true}  
    -- add player to the ui 
    UI:SendMessage( "UpdateSurvivalSummary", {{"user", player }} )    
                        
    freezePlayer(player)
    
    UI:SendMessage( "ToggleActivityCloseButton", {  {"bShow", true}, 
                                            {"GameObject", self}, 
                                            {"MessageName", "toLua"}, 
                                            {"senderID", player} } )
                                            
                                            
    local tempTable = { nameVar = player:GetName().name,
                        timeVar = 0,
                        scoreVar = 0,
                        bConfirm = false }
                        
    self:SetVar("bInit", true)
    
    teamScoreBoard = checkScoreBoardTable(self, tempTable) 
    showScoreBoard(self) 
    UI:SendMessage( "UpdateSurvivalSummary", {{"countdownTime", " " }} )        
end


function onPlayerReady(self)
    --print('onPlayerReady ' .. tostring(GAMEOBJ:GetObjectByID(GAMEOBJ:GetLocalCharID()):GetPlayerReady().bIsReady))
    
    if not GAMEOBJ:GetObjectByID(GAMEOBJ:GetLocalCharID()):GetPlayerReady().bIsReady then
        --print('Try_Ready_Again')
        GAMEOBJ:GetTimer():AddTimerWithCancel( 0.1 , "Try_Ready_Again", self )    
    else
        playerInit(self)
    end
end

function checkScoreBoardTable(self, tScoreBoard, bRemoveTable)
    local tTemp = {}    
    local isUsed = false
    
    for k,v in ipairs(teamScoreBoard) do
        if v.nameVar ~= Localize("SURVIVAL_NO_PLAYER") and v.nameVar ~= tScoreBoard.nameVar and v.nameVar ~= '' then            
            table.insert(tTemp,v)
            --print('add old player to used table ' .. v.nameVar)
        end

        if v.nameVar == tScoreBoard.nameVar then
            if not bRemoveTable then            
                for key,val in pairs(tScoreBoard) do
                    if tostring(val) == tostring(-1) then
                        tScoreBoard[key] = v[key]
                    end
                end
            else
                isUsed = true
            end
        end
    end
    
    if not isUsed then
        table.insert(tTemp,tScoreBoard)    
        --print('add new player to used table ' .. tScoreBoard.nameVar) 
    end   
    
    table.sort(tTemp, function(a,b)
                return a.nameVar<b.nameVar
            end)
    
    if not bFirstTime then
        table.sort(tTemp, function(a,b)
                    return a.timeVar>b.timeVar
                end)                       
    end
    
    self:SetVar("playerNum", table.maxn(tTemp))
        
    while table.maxn(tTemp) < 4 do
        local tempName = ""
        
        --if table.maxn(tTemp) < self:GetNetworkVar("NumberOfPlayers") then
        if table.maxn(tTemp) < 6 then
            tempName = Localize("SURVIVAL_NO_PLAYER")
        end
        
        table.insert(tTemp, {   nameVar =  "",
                                timeVar = 0,
                                scoreVar = 0,
                                bConfirm = false})
    end
    
    return tTemp
end

function SecondsToClock(sSeconds)
    local nSeconds = tonumber(sSeconds)
    
	if nSeconds == 0 or not nSeconds then
		return "--"
	else		
        nHours = string.format("%01.f", math.floor(nSeconds/3600));
        nMins = string.format("%02.f", math.floor(nSeconds/60 - (nHours*60)));
        nSecs = string.format("%02.f", math.floor(nSeconds - nHours*3600 - nMins *60));
        
        if nHours ~= "0" then
			return nHours..":"..nMins..":"..nSecs
        end
        
        return nMins..":"..nSecs 
    end
end

function numToString(iNum)
    if bFirstTime and (iNum == 0 or iNum == nil) then
       return "--"
    end
    
    return tostring(iNum)
end

function showScoreBoard(self, bUpdateOnly)
    p = teamScoreBoard
   
    if not p or not self:GetVar("bInit") then return end    
        
    local messageName = "UpdateSurvivalSummary"
    local messageArgs = {{ "p1_check", p[1].bConfirm }, -- checkmarks
                        { "p2_check",  p[2].bConfirm },
                        { "p3_check",  p[3].bConfirm },
                        { "p4_check",  p[4].bConfirm },
                        { "p1_name", p[1].nameVar }, -- names
                        { "p2_name", p[2].nameVar },
                        { "p3_name", p[3].nameVar },
                        { "p4_name", p[4].nameVar },
                        { "p1_time", SecondsToClock(p[1].timeVar) }, -- times
                        { "p2_time", SecondsToClock(p[2].timeVar) },
                        { "p3_time", SecondsToClock(p[3].timeVar) },
                        { "p4_time", SecondsToClock(p[4].timeVar) },
                        { "p5_time", SecondsToClock(p[1].timeVar) },
                        { "p1_score", numToString(p[1].scoreVar) }, -- score
                        { "p2_score", numToString(p[2].scoreVar) },
                        { "p3_score", numToString(p[3].scoreVar) },
                        { "p4_score", numToString(p[4].scoreVar) },
                        { "p5_score", numToString(p[1].scoreVar + p[3].scoreVar + p[2].scoreVar + p[4].scoreVar) }}
    
    --for k,v in ipairs(p) do print("**"..p[k].nameVar) end
    if not bUpdateOnly then
        -- Hide timer ui
        UI:SendMessage( "ToggleSurvivalScoreboard", {{"visible", false }})
        messageName = "ToggleSurvivalSummary"
        table.insert(messageArgs, { "visible", true })        
    end
    
	-- Show UI
	UI:SendMessage(messageName, messageArgs ) 
	
	UI:SendMessage( "ToggleSurvivalScoreboard", {{"visible", false }} )       
end

function freezePlayer(self, bFreeze)    
    local playerID = GAMEOBJ:GetObjectByID(GAMEOBJ:GetLocalCharID())  
    local eChangeType = "POP"
        
    --if bFreeze and not self:GetNetworkVar('wavesStarted') then
    if bFreeze then
        if playerID:IsDead().bDead then
            --print('frozen')
            GAMEOBJ:GetTimer():AddTimerWithCancel( 0.1 , "Try_Freeze_Again", self )
            return
        
        elseif not playerID:GetStunned().bCanMove then 
            return
        end

        eChangeType = "PUSH"
    end
    
    playerID:SetStunned{ StateChangeType = eChangeType,
                        bCantMove = true, bCantAttack = true, bCantInteract = true }
                        
    
    --print('Player ' .. playerID:GetName().name .. ' ' .. eChangeType .. ' is frozen: ' .. tostring(self:GetVar('frozen')) .. ' ' .. tostring(playerID:GetStunned().bCanMove))
    if playerID:GetStunned().bCanMove and eChangeType == "PUSH" then
        --print(playerID:GetName().name .. ' is still able to move')
        GAMEOBJ:GetTimer():AddTimerWithCancel( 0.1, "Try_Freeze_Again", self )
    end
end

function onNotifyClientObject(self, msg)
    if msg.name == "ToggleLeaderBoard" and msg.paramObj:GetID() == GAMEOBJ:GetControlledID():GetID() then
        UI:SendMessage("ToggleLeaderboard", { {"id",  msg.param1}, {"visible", true}, {"nextOnly", true} } )    
    end
end

----------------------------------------------------------------
---- variables serialized from the server
----------------------------------------------------------------
function onScriptNetworkVarUpdate(self, msg)    
    local player = GAMEOBJ:GetObjectByID(GAMEOBJ:GetLocalCharID())
    
    -- these need to happen first
    for k,v in pairs(msg.tableOfVars) do    
        -- check to see if we have the correct message and deal with it
        if string.starts(k,"Update_ScoreBoard_Players") then  
            local tempPlayer = GAMEOBJ:GetObjectByID(v)               
            
            if tempPlayer:Exists() then                 
                --print("** Update_ScoreBoard_Players " .. tempPlayer:GetName().name)
                local tempTable = { nameVar = tempPlayer:GetName().name,
                                    timeVar = 0,
                                    scoreVar = 0,
                                    bConfirm = false }
                                    
                teamScoreBoard = checkScoreBoardTable(self, tempTable)
                UI:SendMessage( "UpdateSurvivalSummary", {{"countdownTime", " " }} )    
            end
        elseif string.starts(k,"PlayerConfirm_ScoreBoard") then     
            local tempPlayer = GAMEOBJ:GetObjectByID(v)         
 
            if tempPlayer:Exists() then                 
                --print("** PlayerConfirm_ScoreBoard " .. tempPlayer:GetName().name)
                local tempTable = { nameVar = tempPlayer:GetName().name,
                                    timeVar = -1,
                                    scoreVar = -1,
                                    bConfirm = true }
                                    
                teamScoreBoard = checkScoreBoardTable(self, tempTable)      
                showScoreBoard(self, true)
            end
        elseif k == "Update_Default_Start_Timer" then
            if self:GetVar("displayDeath") then
				-- rampart change @TODO
               -- UI:SendMessage( "UpdateSurvivalScoreboard", {{"iplayerName", "Next Round In"}, 
               --                             {"itime", SecondsToClock( v )} } )   
            end
            
            if v == 0 then
                UI:SendMessage( "UpdateSurvivalSummary", {  {"visible", true}, 
                                                            {"countdownTime", v },
                                                            { "p1_check", true }, -- checkmarks
                                                            { "p2_check", true },
                                                            { "p3_check", true },
                                                            { "p4_check", true } } )              
            else
                UI:SendMessage( "UpdateSurvivalSummary", {{"visible", true}, {"countdownTime", v }} )  
            end
        elseif k == "Update_TimerNOTMATCHRAMPART" then -- @TODO RAMPART
            if self:GetVar("displayDeath") then
				-- @todo rampart change
               -- UI:SendMessage( "UpdateSurvivalScoreboard", {{"iplayerName", Localize("SURVIVAL_DEAD_LEFT_SIDE_NAME_PLATE")}, 
               --                             {"itime", SecondsToClock( v )} } )   
            else            
                if not self:GetVar("bShowedPlayer") then     
                    setNextHighScore(self)
                end
                
                -- rampart @todo
                --if self:GetVar("HoldingTopScore") then
                --    UI:SendMessage( "UpdateSurvivalScoreboard", {{"itime", SecondsToClock( v ) }, 
                --                                {"inextbesttime",  SecondsToClock(v) },
                --                                {"inextbestname", player:GetName().name } } )   
               -- else        
                --    UI:SendMessage( "UpdateSurvivalScoreboard", {{"itime", SecondsToClock( v ) } })
                 --   checkNextHighScore(self, v)
               -- end
            end
        end
    end
    
    for k,v in pairs(msg.tableOfVars) do
        -- check to see if we have the correct message and deal with it
        if k == "Show_ScoreBoard" then
            if bFirstTime then
                --print("--> Show_ScoreBoard " .. player:GetName().name)    
                showScoreBoard(self)
            end
                    
            freezePlayer(self, true)
            
            -- clear game vars
            self:SetVar("HoldingTopScore", false)
            self:SetVar("NextBest", false )  	
            self:SetVar("NextBestName", false)	
            self:SetVar("bShowedPlayer", false)
            self:SetVar("FoundPlayer", false )
           
        elseif k == "Exit_Waves" then    
            local tempPlayer = GAMEOBJ:GetObjectByID(v)                        
            local tempTable = { nameVar = tempPlayer:GetName().name,
                                timeVar = 0,
                                scoreVar = 0,
                                bConfirm = false}
            
            if player:GetID() == v then     
                break
            end
            
            if #teamScoreBoard > 0 then
                teamScoreBoard = checkScoreBoardTable(self, tempTable, true)
                showScoreBoard(self, true)
            end
        elseif k == "Start_Wave_Message" then
            self:SetVar("displayDeath", false)
            -- @TODO removed as a test for rampart
            --UI:SendMessage("ToggleLeaderboard", { {"id",  v},{"visible", false} } )
            player:ShowActivityCountdown()
            --UI:SendMessage( "UpdateSurvivalScoreboard", {{"itime", "00:00"},{"iplayerName", player:GetName().name}} )
            bFirstTime = false
            freezePlayer(self)
        elseif k == "Clear_Scoreboard" then                 
            UI:SendMessage( "UpdateSurvivalSummary", {  {"countdownTime", " " },
                                                        {"p1_check",  false },
                                                        {"p2_check",  false },
                                                        {"p3_check",  false },
                                                        {"p4_check",  false }} )  
            -- remove ui timer
            UI:SendMessage( "ToggleSurvivalSummary", {  {"visible", false },} )    
            -- add ui timer      
            -- @TODO rampart  
           -- UI:SendMessage( "ToggleSurvivalScoreboard", {{"visible", true }, {"itime", "00:00"}} )
            teamScoreBoard = {}            
        end
    end
end

function onNotifyClientZoneObject(self, msg) 
    if msg.name == "Update_ScoreBoard" then  
        if not msg.paramObj:Exists() then return end
        
        --print('update player ' .. msg.paramObj:GetName().name)
        local tempTable = { nameVar = msg.paramObj:GetName().name,
                            timeVar = msg.param1,
                            scoreVar = tonumber(msg.paramStr),
                            bConfirm = false }
                            
        teamScoreBoard = checkScoreBoardTable(self, tempTable)
    end
end

function ExitBox(self, player)
	print("EXIT BOX")
    local player = GAMEOBJ:GetObjectByID(GAMEOBJ:GetLocalCharID()) 	
    
    if player:Exists() then
		local text = Localize("SURVIVAL_EXIT_QUESTION")
		
		--if self:GetNetworkVar("wavesStarted") then
			text = Localize("SURVIVAL_PLAYING_EXIT_QUESTION") -- "Your time will not be recorded if you exit before the game is over. Exit anyway?"
		--end
		
        -- display exit box
        player:DisplayMessageBox{bShow = true, 
                         imageID = 1, 
                         text = text, 
                         callbackClient = self, 
                         identifier = "Exit_Question"}
    end
end
----------------------------------------------------------------
-- Sent from a player when responding from a messagebox
----------------------------------------------------------------
function onMessageBoxRespond(self, msg)        
    if msg.identifier == "LeaderboardNext" then
        -- when the player hits the next button on the survival leaderboard
        UI:SendMessage( "popGameState", {{"state", "SurvivalLeaderboard"}})
        self:SetVar("displayDeath", false)
        showScoreBoard(self)
    elseif msg.identifier == "ActivityCloseButtonPressed" and msg.iButton == -1 then  
        -- when the player hits the activity close button, the x in the top right
        ExitBox(self, player)        
    elseif msg.identifier == "Exit" and msg.iButton == 1 then 
        -- when the player hits the exit button on the survival summary UI
        ExitBox(self, player)
    elseif msg.identifier == "Exit_Question" and msg.iButton == 1 then      
        -- when the player hit's the check box on the exit question message box clear all the survival UI elements
        UI:SendMessage( "ToggleActivityCloseButton", {{"bShow", false}} )  
        UI:SendMessage("ToggleSurvivalSummary", {{"visible", false }}) 
        UI:SendMessage( "ToggleSurvivalScoreboard", {{"visible", false }} )
        UI:SendMessage("ToggleLeaderboard", { {"id",  msg.identifier},{"visible", false} } )
        UI:SendMessage( "popGameState", {{"state", "Survival"}} )
        UI:SendMessage( "popGameState", {{"state", "SurvivalLeaderboard"}})
    end
end

function onSendActivitySummaryLeaderboardData(self, msg)
    --print('Activity Summary Sent to client Zone')    
    if (msg) then
	    self:SetVar("HoldingTopScore", false) 

        local player = GAMEOBJ:GetObjectByID(GAMEOBJ:GetLocalCharID()) 		
        local MaxCount = msg.leaderboardData["Result[0].RowCount"] or 0
        local tableValues = {}
        
        for i = 0, MaxCount do       
			local name = msg.leaderboardData["Result[0].Row["..i.."].name"] 
			
			table.insert(tableValues, name)
			table.insert(tableValues, msg.leaderboardData["Result[0].Row["..i.."].Time"])

			if msg.leaderboardData["Result[0].Row["..i.."].Relationship"]  then    
				if msg.leaderboardData["Result[0].Row["..i.."].Relationship"] ~= 0 then 
					self:SetVar("FoundFriendGuild", true )
				end
			end			
			
			-- found the player so dont record the other values
			if name == player:GetName().name then 				
				self:SetVar("FoundPlayer", true )
				
				break 
			end
        end
     
        self:SetVar("bShowedPlayer", false)          
        self:SetVar("NextBest", false)  	
        self:SetVar("NextBestName", false)	
        self:SetVar("LeaderTable", tableValues)         
        setNextHighScore(self)
    end
end

function setNextHighScore(self, iScore)
    local player = GAMEOBJ:GetObjectByID(GAMEOBJ:GetLocalCharID()) 			
    local name_value = 0
    local score_value = 0
    local name = 0    
    local score = 0
    local tableValues = self:GetVar("LeaderTable") or {}
    local curName = self:GetVar("NextBestName")
    local playerScore = 0
     
    if not curName then
        curName = player:GetName().name
    end
    
    for testName = 1, table.maxn(tableValues) do            
        if tableValues[testName] == curName then
            name = testName
            score = (testName + 1)     
            
            if name ~= 1 then 
                name_value = (testName - 2)
                score_value = (testName - 1)
            elseif name_value == 3 then
                name_value = 1
                score_value = 2
            elseif name_value == 1 then
                name_value = 1
                score_value = 2
            end
        end            
        
		if tableValues[testName] == player:GetName().name then
			playerScore = tableValues[(testName + 1)]
		end
	end        
        
    local uiName = tableValues[name] or player:GetName().name
    local uiScore = tableValues[score] or playerScore
    local uiNextName = tableValues[name_value] or player:GetName().name
    local uiNextScore = tableValues[score_value] or playerScore
                        
    if not self:GetVar("bShowedPlayer") then     
        uiNextName = uiName
        uiNextScore = uiScore		   
    end
    
    if not iScore then 
        iScore = 0
    end
            
    local tempMedals = tMedals
    
    if self:GetVar("playerNum") == 1 then
        tempMedals = tMedalsSolo
    end
    
    local highestScore = tableValues[2] or 0
    local missionCheck = player:GetMissionState{missionID = checkMission}.missionState < 4 and iScore < checkMissionTime
    
    if missionCheck then    
		uiNextName = Localize("Missions_479_name")
		uiNextScore = checkMissionTime
    elseif iScore >= math.floor(highestScore) or not self:GetVar("FoundPlayer") then
        local pass = false
        
        for k,v in ipairs(tempMedals) do
            if iScore < v.score then
                uiNextName = v.name
                uiNextScore = v.score
                pass = true
                break
            end
        end
        
        if not pass then
            self:SetVar("HoldingTopScore", true) 
            uiNextName = player:GetName().name
            uiNextScore = iScore      
        end      
    end    
    
    if not self:GetVar("displayDeath") then    
		local messageName = "UpdateSurvivalScoreboard"
		
		if self:GetVar("bShowedPlayer") then
			UI:SendMessage(messageName, { 	{"visible", true },
										{"iplayerName", player:GetName().name}, 
										{"inextbesttime",  SecondsToClock(uiNextScore) }, 
										{"inextbestname", tostring(uiNextName) } } ) 
		end
		
    end
    
    self:SetVar("NextBest", math.floor(uiNextScore) )  	
    self:SetVar("NextBestName", uiNextName )	
    self:SetVar("bShowedPlayer", true)
end

function checkNextHighScore(self, iScore)
    if not iScore or not self:GetVar('NextBest') then return end
    
    if iScore >= self:GetVar('NextBest') then        
        setNextHighScore(self, iScore)
    end
end

function onTimerDone(self, msg)
    if msg.name == "Try_Freeze_Again" then    
        freezePlayer(self, true)
    elseif msg.name == "Try_Ready_Again" then
        PlayerReady(self)
    end
end