-- (VR) Screen effects --------------
function VRBaseCamera:StartFadeFromBlack()
	if UserGameSettings.VignetteEnabled == false then
		return
	end

	local VRFade = Lighting:FindFirstChild("VRFade")
	if not VRFade then
		VRFade = Instance.new("ColorCorrectionEffect")
		VRFade.Name = "VRFade"
		VRFade.Parent = Lighting
	end
	VRFade.Brightness = -1
	self.VRFadeResetTimer = 0.1
end

function VRBaseCamera:UpdateFadeFromBlack(timeDelta: number)
	local VRFade = Lighting:FindFirstChild("VRFade")
	if self.VRFadeResetTimer > 0  then
		self.VRFadeResetTimer = math.max(self.VRFadeResetTimer - timeDelta, 0)

		local VRFade = Lighting:FindFirstChild("VRFade")
		if VRFade and VRFade.Brightness < 0 then
			VRFade.Brightness = math.min(VRFade.Brightness + timeDelta * VR_FADE_SPEED, 0)
		end
	else
		if VRFade then -- sanity check, VRFade off
			VRFade.Brightness = 0
		end
	end
end

function VRBaseCamera:StartVREdgeBlur(player)
	if UserGameSettings.VignetteEnabled == false then
		return
	end

	local blurPart = nil
	blurPart = (workspace.CurrentCamera :: Camera):FindFirstChild("VRBlurPart")
	if not blurPart then
		local basePartSize = Vector3.new(0.44,0.47,1)
		blurPart = Instance.new("Part")
		blurPart.Name = "VRBlurPart"
		blurPart.Parent = workspace.CurrentCamera
		blurPart.CanTouch = false
		blurPart.CanCollide = false
		blurPart.CanQuery = false
		blurPart.Anchored = true
		blurPart.Size = basePartSize
		blurPart.Transparency = 1
		blurPart.CastShadow = false

		RunService.RenderStepped:Connect(function(step)
			local userHeadCF = VRService:GetUserCFrame(Enum.UserCFrame.Head)

			local vrCF = (workspace.CurrentCamera :: Camera).CFrame * (CFrame.new(userHeadCF.p * (workspace.CurrentCamera :: Camera).HeadScale) * (userHeadCF - userHeadCF.p))
			blurPart.CFrame = (vrCF * CFrame.Angles(0, math.rad(180), 0)) + vrCF.LookVector * (1.05 * (workspace.CurrentCamera :: Camera).HeadScale)
			blurPart.Size = basePartSize * (workspace.CurrentCamera :: Camera).HeadScale
		end)
	end

	local VRScreen = player.PlayerGui:FindFirstChild("VRBlurScreen")
	local VRBlur = nil
	if VRScreen then
		VRBlur = VRScreen:FindFirstChild("VRBlur")
	end

	if not VRBlur then
		if not VRScreen then
			VRScreen = Instance.new("SurfaceGui") or Instance.new("ScreenGui")
		end

		VRScreen.Name = "VRBlurScreen"
		VRScreen.Parent = player.PlayerGui

		VRScreen.Adornee = blurPart

		VRBlur = Instance.new("ImageLabel")
		VRBlur.Name = "VRBlur"
		VRBlur.Parent = VRScreen

		VRBlur.Image = "rbxasset://textures/ui/VR/edgeBlur.png"
		VRBlur.AnchorPoint = Vector2.new(0.5, 0.5)
		VRBlur.Position = UDim2.new(0.5, 0, 0.5, 0)

		-- this computes the ratio between the GUI 3D panel and the VR viewport
		-- adding 15% overshoot for edges on 2 screen headsets
		local ratioX = (workspace.CurrentCamera :: Camera).ViewportSize.X * 2.3 / VR_PANEL_SIZE
		local ratioY = (workspace.CurrentCamera :: Camera).ViewportSize.Y * 2.3 / VR_PANEL_SIZE

		VRBlur.Size = UDim2.fromScale(ratioX, ratioY)
		VRBlur.BackgroundTransparency = 1
		VRBlur.Active = true
		VRBlur.ScaleType = Enum.ScaleType.Stretch
	end

	VRBlur.Visible = true
	VRBlur.ImageTransparency = 0
	self.VREdgeBlurTimer = VR_SCREEN_EGDE_BLEND_TIME
end

function VRBaseCamera:UpdateEdgeBlur(player, timeDelta)
	local VRScreen = player.PlayerGui:FindFirstChild("VRBlurScreen")
	local VRBlur = nil
	if VRScreen then
		VRBlur = VRScreen:FindFirstChild("VRBlur")
	end

	if VRBlur then
		if self.VREdgeBlurTimer > 0 then
			self.VREdgeBlurTimer = self.VREdgeBlurTimer - timeDelta

			local VRScreen = player.PlayerGui:FindFirstChild("VRBlurScreen")
			if VRScreen then
				local VRBlur = VRScreen:FindFirstChild("VRBlur")
				if VRBlur then
					VRBlur.ImageTransparency = 1.0 - math.clamp(self.VREdgeBlurTimer, 0.01,
						VR_SCREEN_EGDE_BLEND_TIME) * (1/VR_SCREEN_EGDE_BLEND_TIME)
				end
			end
		else
			VRBlur.Visible = false
		end
	end
end

function VRBaseCamera:GetCameraHeight()
	if not self.inFirstPerson then
		return math.sin(VR_ANGLE) * self.currentSubjectDistance
	end
	return 0
end

function VRBaseCamera:GetSubjectCFrame(): CFrame
	local result = BaseCamera.GetSubjectCFrame(self)
	local camera = workspace.CurrentCamera
	local cameraSubject = camera and camera.CameraSubject

	if not cameraSubject then
		return result
	end

	-- new VR system overrides
	if cameraSubject:IsA("Humanoid") then
		local humanoid = cameraSubject
		local humanoidIsDead = humanoid:GetState() == Enum.HumanoidStateType.Dead

		if humanoidIsDead and humanoid == self.lastSubject then
			result = self.lastSubjectCFrame
		end
	end

	if result then
		self.lastSubjectCFrame = result
	end

	return result
end

function VRBaseCamera:GetSubjectPosition(): Vector3?
	local result = BaseCamera.GetSubjectPosition(self)

	-- new VR system overrides
	local camera = game.Workspace.CurrentCamera
	local cameraSubject = camera and camera.CameraSubject
	if cameraSubject then
		if cameraSubject:IsA("Humanoid") then
			local humanoid = cameraSubject
			local humanoidIsDead = humanoid:GetState() == Enum.HumanoidStateType.Dead

			if  humanoidIsDead and humanoid == self.lastSubject then
				result = self.lastSubjectPosition
			end
		elseif cameraSubject:IsA("VehicleSeat") then
			local offset = VR_SEAT_OFFSET
			result = cameraSubject.CFrame.p + cameraSubject.CFrame:vectorToWorldSpace(offset)
		end
	else
		return nil
	end

	self.lastSubjectPosition = result

	return result
end