--------------------------------------------------------------
-- (SERVER SIDE) Obstacle Course Starter NPC
-- Starts the course for the player and runs the logic
--
-- updated mrb... 6/9/11 - refactored
--------------------------------------------------------------

local MS_IN_SEC = 1000
local missionIDs = {1884}
----------------------------------------------------------------
-- Startup of the object
----------------------------------------------------------------
function onStartup(self) 
    -- set max users to something high
    self:SetActivityParams{ modifyActivityActive=true, activityActive = true, maxUsers = 9999, modifyMaxUsers = true }    
    self:SendLuaNotificationRequest{requestTarget=GAMEOBJ:GetZoneControlID(), messageName="PlayerExit"}    
    self:SetProximityRadius{radius = self:GetInteractionDistance().fDistance + 10, name = "Interaction_Distance"}
end

----------------------------------------------------------------
-- Returns true/false if a player is in the activity
-- takes SELF and a PLAYER object
----------------------------------------------------------------
function IsPlayerInActivity(self, player)
    -- check if player is in activity
    local existMsg = self:ActivityUserExists{ userID = player }
    
    if existMsg then
        return existMsg.bExists
    end
    
    return false
end

----------------------------------------------------------------
-- Happens on interaction for server
----------------------------------------------------------------
function onUse(self, msg)
    -- get player who clicked on us
	local player = msg.user
	
    if not checkInProximity(self,  player) then return end
       
    if player:GetFlag{iFlagID = 115}.bFlag then        
        player:DisplayMessageBox{bShow = true, imageID = 1, callbackClient = self, text = "FOOT_RACE_STOP_QUESTION", identifier = "FootRaceCancel"}
            
    else
        -- check if player is in course
        if IsPlayerInActivity(self, player) then
            -- offer exit
			self:NotifyClientObject{name = "exit", rerouteID = player}
            
        else
            -- offer start activity    
			self:NotifyClientObject{name = "start", rerouteID = player}
        end    
    end
end

function checkInProximity(self, player)
    local proxObjects = self:GetProximityObjects{name = "Interaction_Distance"}.objects

    for k,v in ipairs(proxObjects) do
        if v:GetID() == player:GetID() then
            return true
        end
    end
    
    return false
end

----------------------------------------------------------------
-- Sent from a player when responding from a messagebox
----------------------------------------------------------------
function onMessageBoxRespond(self, msg)
    -- Response to Exit activity dialog and user pressed OK
    if msg.identifier == "player_dialog_cancel_course" and msg.iButton == 1 then
        -- remove the user
        self:RemoveActivityUser{ userID = msg.sender }
        self:NotifyClientObject{name = "cancel_timer", rerouteID = msg.sender}
    -- Response to Start activity dialog and ok is pressed and player is not in activity
    elseif msg.identifier == "player_dialog_start_course" and msg.iButton == 1 and IsPlayerInActivity(self, msg.sender) == false then
        if not checkInProximity(self,  msg.sender) then 
            self:NotifyClientObject{name = "out_of_bounds", rerouteID = msg.sender}     
            return 
        end
                
        -- add the new user
        self:AddActivityUser{ userID = msg.sender }
        
        -- start the activity for the new user
        StartActivity(self, msg.sender)
    elseif msg.identifier == "FootRaceCancel" and msg.iButton == 1 then    
        local tFootRaceStarters = self:GetObjectsInGroup{ group = 'FootRaceStarter', ignoreSpawners = true }.objects
        
        for k,v in ipairs(tFootRaceStarters) do
            -- remove the user
            if IsPlayerInActivity(v, msg.sender) then
                v:NotifyClientObject{name = "stop_timer" , rerouteID = msg.sender}
                
                break
            end
        end
        
        -- check if player is in course
        if IsPlayerInActivity(self, msg.sender) == true then
            -- offer exit
			self:NotifyClientObject{name = "exit", rerouteID = msg.sender}
            
        else
            -- offer start activity    
			self:NotifyClientObject{name = "start", rerouteID = msg.sender}
        end   
        
                
        -- turn off the player flag for is player in foot race
        msg.sender:SetFlag{iFlagID = 115, bFlag = false}
    end
end

----------------------------------------------------------------
-- Stores the start time for the player in the activity and
-- sends messages to start it
----------------------------------------------------------------
function StartActivity(self, player)    
    -- get the current time in sec
    local startTime = (GAMEOBJ:GetSystemTime() / MS_IN_SEC) + 4
    
    self:NotifyClientObject{name = "start_timer" , rerouteID = player}
    self:SetActivityUserData{ userID = player, typeIndex = 1, value = tonumber(startTime) }
end

----------------------------------------------------------------
-- Handle FireEvent message
----------------------------------------------------------------
function onFireEvent(self, msg)
    -- user is trying to cancel
    if msg.args == "course_cancel" and IsPlayerInActivity(self, msg.senderID) then
        self:NotifyClientObject{name = "cancel_timer", rerouteID = msg.senderID}        
        -- remove the user from activity
        self:RemoveActivityUser{ userID = msg.senderID }        
    elseif msg.args == "course_finish" and IsPlayerInActivity(self, msg.senderID) then
        -- store the finish time in sec
        local endTime = GAMEOBJ:GetSystemTime() / MS_IN_SEC
    
        -- store the time as activity rating [1]
        self:SetActivityUserData{ userID = msg.senderID, typeIndex = 2, value = tonumber(endTime) }
        -- distribute rewards        
        self:DistributeActivityRewards{ userID = msg.senderID, bAutoAddCurrency = true, bAutoAddItems = true  }        
        -- do complete activity events
        self:CompleteActivity{ userID = msg.senderID}        
        -- remove the user from activity
        self:RemoveActivityUser{ userID = msg.senderID }            
    end
end

----------------------------------------------------------------
-- Player has exited the map
----------------------------------------------------------------
function notifyPlayerExit(self, other, msg)
    if IsPlayerInActivity(self, msg.playerID) then        
        -- remove the user from activity
        self:RemoveActivityUser{ userID = msg.playerID }
    end
end

--------------------------------------------------------------
-- Passes start/end time and gets the total time
--------------------------------------------------------------
function GetTotalTime(startTime, endTime)
    -- calculate total time (subtract countdown and cap at 0)
    local totalTime = tonumber(endTime) - tonumber(startTime)
    
    if totalTime < 0 then
        totalTime = 0
    end        

    return math.floor(totalTime)    
end

--------------------------------------------------------------
-- Called when the activity is trying to calculate final rating
--------------------------------------------------------------
function onDoCalculateActivityRating(self, msg)
    -- get the time for the player    
    local totalTime = GetTotalTime(msg.fValue2, msg.fValue3)
    
    msg.outActivityRating = totalTime
    
    return msg
end

--------------------------------------------------------------
-- Called when the activity is trying to complete
--------------------------------------------------------------
function onDoCompleteActivityEvents(self, msg)
    -- get the time for the player    
    local totalTime = GetTotalTime(msg.fValue2, msg.fValue3)

    self:SetActivityUserData{ userID = msg.userID, typeIndex = 1, value = tonumber(totalTime) }	    
    --total time has to be negative for perform activity task to function properly
    msg.userID:UpdateMissionTask{ taskType = "performact_time", value2 = self:GetActivityID().activityID, value = totalTime * -1 }    
    
    for k,mission in ipairs(missionIDs) do
		msg.userID:UpdateMissionTask{taskType = "complete", value = mission, value2 = 1, target = self}
	end

    -- Update Leaderboards for this user
    self:UpdateActivityLeaderboard{ userID = msg.userID }

    local actID = self:GetActivityID().activityID
    
    -- get the leaderboard data for the user and update summary screen if it exists
    msg.userID:RequestActivitySummaryLeaderboardData{target = self, queryType = 1, gameID = actID }
    self:NotifyClientObject{name = "ToggleLeaderBoard", param1 = actID, paramObj = msg.userID , rerouteID = msg.userID} 
    --print(msg.senderID:GetName().name .. ' finished the race')    
    self:NotifyClientObject{name = "stop_timer" , param1 = 1, param2 = totalTime, rerouteID = msg.userID}
end 