--[[
	Used for setting the default selection for a gamepad.

	When mounted, this component will set its Parent as
	`GuiService.SelectedObject` so that the gamepad has an element to interact
	with by default.

	Usage:

	    Roact.createElement("ImageButton", {
	        Image = ...
	        Size = UDim2.fromOffset(200, 50),
	    }, {
	        SelectParent = Roact.createElement(SelectParent)
	    })
]]


local GuiService = game:GetService("GuiService")
local UserInputService = game:GetService("UserInputService")

local ExperienceComponents = script:FindFirstAncestor("ExperienceComponents")

local Roact = require(ExperienceComponents.Parent.Roact)
local ExternalEventConnection = require(ExperienceComponents.Parent.ExternalEventConnection)
local onInstanceLoaded = require(ExperienceComponents.Modules.onInstanceLoaded)
local getCurrentDevice = require(ExperienceComponents.Modules.getCurrentDevice)
local enums = require(ExperienceComponents.enums)

local SelectParent = Roact.Component:extend("SelectParent")

export type Props = {
	playerGuiClass: string,
	GuiService: GuiService,
	UserInputService: UserInputService,
}

export type State = {
	device: string,
	selection: GuiObject,
}

SelectParent.defaultProps = {
	playerGuiClass = "PlayerGui",
	GuiService = GuiService,
	UserInputService = UserInputService,
}

function SelectParent:init()
	self.ref = Roact.createRef()

	self.setCurrentDevice = function()
		local props: Props = self.props

		local lastInputType = props.UserInputService:GetLastInputType() or Enum.UserInputType.Keyboard

		self:setState({
			device = getCurrentDevice(lastInputType),
		})
	end
end

function SelectParent:render()
	local props: Props = self.props

	return Roact.createElement("Folder", {
		[Roact.Ref] = self.ref,
	}, {
		LastInputTypeChanged = Roact.createElement(ExternalEventConnection, {
			event = props.UserInputService.LastInputTypeChanged,
			callback = self.setCurrentDevice,
		}),
	})
end

function SelectParent:didUpdate(_, prevState: State)
	local state: State = self.state
	local props: Props = self.props

	if state ~= prevState then
		if state.device == enums.Device.Gamepad then
			props.GuiService.SelectedObject = state.selection
		end
	end
end

function SelectParent:didMount()
	local props: Props = self.props
	local instance: Folder = self.ref:getValue()

	self.setCurrentDevice()

	onInstanceLoaded(instance, function()
		-- Setting SelectedObject to an instance that is not a descendant of a
		-- PlayerGui throws an error. This is used to suppress that error in stories
		-- since they are parented to CoreGui.
		if not instance:FindFirstAncestorOfClass(props.playerGuiClass) then
			return
		end

		self:setState({
			selection = instance.Parent,
		})
	end)
end

return SelectParent
