-- ================================================================================
-- LOCAL FUNCTIONS
-- ================================================================================

local function openInfoGui()
	InfoFrame.Visible = true
	
	if not (blurEffect) then
		blurEffect = Instance.new("BlurEffect")
		blurEffect.Size = 12
		blurEffect.Parent = game.Lighting
	end
end -- openInfoGui()

local function exitInfoGui()
	if blurEffect then
		blurEffect:Destroy()
		blurEffect = false
	end
	InfoFrame.Visible = false
end -- exitInfoGui

local function moveModelForViewport(model)
	-- Performed only to reset model orientation, position does not matter
	model:MoveTo(MODEL_POSITION)
	
	-- Set position so that all models have the same orientation and position
	model.PrimaryPart = model:FindFirstChild("Body")
	if model.PrimaryPart then
		model:SetPrimaryPartCFrame(MODEL_CFRAME)
	end
end -- moveModelForViewport()

local function highlightViewport(viewport)
	for _, child in ipairs(Container:GetChildren()) do
		if child:IsA("ViewportFrame") then
			if child == viewport then
				child.BorderColor3 = Color3.new(15/255, 128/255, 255/255)
			else
				child.BorderColor3 = Color3.new(1, 1, 1)
			end
		end
	end
end

local function unselectButtons()
	local viewports = Container:GetChildren()
	
	for _, viewport in ipairs(viewports) do
		if viewport:IsA("ViewportFrame") then
			local button = viewport:FindFirstChild("Button")
			if button ~= nil then
				button.Image = "rbxassetid://4079511969"
			end
		end
	end
end -- unselectButton()

local function clearSelected()
	highlightViewport(nil)
	
	Selected:FindFirstChild("Garage").Value = nil
	
	local selectedModels = Selected:GetChildren()
	for _, child in ipairs(selectedModels) do
		if child:IsA("Model") then
			child:Destroy()
		end
	end
	
	SelectedName.Text = ""
end -- clearSelected()

local function exit()
	if InfoFrame.Visible == true then return end
	
	SelectionFrame.Visible = false
	
	unselectButtons()
	highlightViewport(nil)
	clearSelected()
	
	SelectedMode.Value = ""
end -- exit()

local function exitSpeeder()
	ContextActionService:UnbindAction("ExitSpeeder")
	RemoveActivePlayer:FireServer()
	
	local raceStatus = RaceManager:GetRaceStatus()
	if not TopBar.Enabled or (raceStatus ~= RaceManager.Status.WaitingForPlayers and
		raceStatus ~= RaceManager.Status.WaitingForRaceToStart) then
		PlayerConverter:SpeederToPlayer()
	end
end -- exit()

local function makeSelection()
	-- Get selection
	local selection = Selected:FindFirstChild("Garage").Value
	if not selection then return end
	
	-- Act according to selected game mode
	if SelectedMode.Value == "FreeFlight" then
		PlayerConverter:PlayerToSpeeder(selection)
	elseif SelectedMode.Value == "Racing" then
		-- Add player to ActivePlayer of PlayerManager for the RaceModules
		AddActivePlayer:FireServer(selection)
		
		-- Show racing GUIs
		local PlayerGui = player.PlayerGui
		local TopBar = PlayerGui:FindFirstChild("TopBar")
		TopBar.Enabled = true
	end
	
	-- Keybinding to exit
	ContextActionService:BindAction("ExitSpeeder", exitSpeeder, false, KEY1)
	
	-- Close window
	exit()
end -- makeSelection()

local function populateList(folder)
	local count = 0
	
	for index, item in ipairs(folder:GetChildren()) do
		if item:IsA("Model") then
			count = count + 1
			
			-- List is populated with ViewportFrames displaying the folder's models
			local viewport = Instance.new("ViewportFrame")
			viewport.Name = tostring(count)
			viewport.Parent = Container
			viewport.LayoutOrder = 5
			viewport.ZIndex = 2
			viewport.BackgroundTransparency = 1
			viewport.ClipsDescendants = true
			
			-- Create camera for ViewportFrame
			local camera = Instance.new("Camera")
			camera.Parent = viewport
			camera.FieldOfView = 30
			viewport.CurrentCamera = camera
		
			-- Point to (server-side) model
			local newGarageModel = Instance.new("ObjectValue")
			newGarageModel.Parent = viewport
			newGarageModel.Name = "Garage"
			newGarageModel.Value = item
			
			-- Clone model and part it to the ViewportFrame
			local newItem = item:clone()
			newItem.Parent = viewport
			
			-- Move model so that all model viewports are from the same angle
			moveModelForViewport(newItem)
			
			local primary = newItem.PrimaryPart
			local primarySize = primary.Size
			
			-- Adjust camera to look at the model
			local cameraPosition = primary.Position + Vector3.new(0, primarySize.Y + 10, -primarySize.Z*1.8)
			camera.CFrame = CFrame.new(cameraPosition, newItem.PrimaryPart.Position)
			
			-- Overlay viewport with a button
			local button = Instance.new("ImageButton")
			button.Name = "Button"
			button.Parent = viewport
			button.Size = UDim2.new(1,0,1,0)
			button.BackgroundTransparency = 1
			button.Image = "rbxassetid://4079511969"
			button.HoverImage = "rbxassetid://4079512099"
			button.PressedImage = "rbxassetid://4079512099"
			button.Activated:Connect(function()
				local selection = Selected:FindFirstChild(SelectedName.Text)
				local garageModel = Selected:FindFirstChild("Garage")
				clearSelected()
				
				unselectButtons()
				button.Image = "rbxassetid://4079512099"
				
				garageModel.Value = newGarageModel.Value
				
				local selectedItem = newItem:clone()
				selectedItem.Parent = Selected
				
				SelectedName.Text = string.upper(selectedItem.Name)
				
				local primary = selectedItem.PrimaryPart
				local primarySize = primary.Size
			
				local cameraPosition = newItem.PrimaryPart.Position + Vector3.new(0, primarySize.Y + 15, -primarySize.Z*1.8)
				SelectedCamera.CFrame = CFrame.new(cameraPosition, newItem.PrimaryPart.Position)
			end)
		end
		
		-- Scale ScrollingFrame to fit list
		Container.CanvasSize = UDim2.new(1*math.ceil(count/6), 0, 0, 0)
		UIGridLayout.CellSize = UDim2.new((1/3)/math.ceil(count/6), -4, 0.5, -2)
	end
end -- populateList()