-- ================================================================================
-- PUBLIC FUNCTIONS
-- ================================================================================

function RaceModule:SetRacers(racerList)
	for i = 1, #racerList do
		addRacer(racerList[i])
	end
end -- RaceModule:SetRacers()

function RaceModule:RegisterCheckpoint(checkpoint)
	if not checkpoints[checkpoint] then
		local newCheckpoint = Checkpoint.new(checkpoint, RaceModule)
		numCheckpoints = numCheckpoints + 1
		checkpoints[checkpoint] = newCheckpoint
	end
end -- RaceModule:RegisterCheckpoint()

function RaceModule:PlayerCrossedCheckpoint(player, checkpoint)
	local racer = racers[player]	
	
	if not racer or racer.FinishedRace then return end
	local currentLap = racer.CurrentLap

	CheckpointEvent:FireClient(player, {{"checkpointHit", checkpoint.CollisionBody}})
	
	if not racer:HasStartedLap(currentLap) then
		racer:StartLap(currentLap)
		onLapStartedEvent:Fire(player, currentLap)
	end
	
	if racer:HasStartedLap(currentLap) then
		local alreadyPassed = checkpoint:SetPlayerPassed(player, currentLap)
		if not alreadyPassed then		
			onCheckpointPassedEvent:Fire(checkpoint.CollisionBody)
		end
	end
	
	if hasPlayerFinishedLap(player, currentLap) then
		local lapTime = racer:FinishLap(currentLap)
		onLapFinishedEvent:Fire(player, currentLap, lapTime)
		if currentLap == numLaps then
			if not winner then
				winner = player
			end
			racer.FinishedRace = true
			onRaceFinishedEvent:Fire(winner)
		else
			wait() -- Let the last checkpoint temporarily change to hit color
			
			CheckpointEvent:FireClient(player, {{"newLap"}})
			
			racer.CurrentLap = racer.CurrentLap + 1
		end
	end
end -- RaceModule:PlayerCrossedCheckpoint()

function RaceModule:Start(activePlayers)
	if debugEnabled then print("RACEMODULE: Starting race") end	
	
	winner = nil
	
	assert(numCheckpoints > 0, "No checkpoints registered")
	
	if debugEnabled then print("RACEMODULE: Checking if players set") end
	if #racers == 0 then
		RaceModule:SetRacers(activePlayers)
	end	
	
	for _, checkpoint in pairs(checkpoints) do
		checkpoint:Reset()
	end

	onRaceStartedEvent:Fire()
	
	local raceOver = false
	local finishedConnection
	finishedConnection = RaceModule.RaceFinished:connect(function()
		raceOver = true
		racers = {}
		finishedConnection:disconnect()
	end)
	spawn(function()
		wait(raceDuration)
		if not raceOver then
			onRaceFinishedEvent:Fire(winner)
		end
	end)
end -- RaceModule:Start()