--[[
	UI to select the surface art to place onto the canvas.
]]


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

SurfaceArtSelector.defaultProps = {
	numItemsPerPage = 3,
}

function SurfaceArtSelector:init()
	self.isAnimating = false
	self.position, self.updatePosition = Roact.createBinding(0)
	self.target, self.updateTarget = Roact.createBinding(0)
	self.motor = Otter.createSingleMotor(self.position:getValue())
	self.motor:onStep(self.updatePosition)

	self.state = {
		-- Selected surface art index in self.props.images
		selectedIndex = 1,

		-- Offset to render overflow items in order to avoid empty items during pagination
		offset = 0,
	}
	self.useSinglePagination = function()
		return UserInputService.TouchEnabled or self.props.orientation.isPortrait
	end
	self.onApply = modules.onApply(self)
	self.onCancel = modules.onCancel(self)
	self.prevPage = function()
		local prevPage = modules.prevPage(self)
		prevPage(math.min(self.props.numItemsPerPage, #self.props.images))
	end
	self.prevItem = function()
		local prevPage = modules.prevPage(self)
		prevPage(1)
	end
	self.nextPage = function()
		local nextPage = modules.nextPage(self)
		nextPage(math.min(self.props.numItemsPerPage, #self.props.images))
	end
	self.nextItem = function()
		local nextPage = modules.nextPage(self)
		nextPage(1)
	end
	self.setCurrentIndex = modules.setCurrentIndex(self)
	self.getRenderedIndexes = modules.getRenderedIndexes(self)
	self.formatTargetIndex = modules.formatTargetIndex()
	self.getItemTransparency = modules.getItemTransparency(self)
end

function SurfaceArtSelector:render()
	local items = {
		UIListLayout = Roact.createElement("UIListLayout", {
			SortOrder = Enum.SortOrder.LayoutOrder,
			FillDirection = Enum.FillDirection.Horizontal,
			VerticalAlignment = Enum.VerticalAlignment.Center,
			HorizontalAlignment = Enum.HorizontalAlignment.Center,
		}),
	}

	local indexes = self.getRenderedIndexes()
	local mid = math.floor((#indexes + 1) / 2)
	for i, index in ipairs(indexes) do
		-- Avoid the same image being shown as selected when they are shown on the same page
		local isSelected = self.state.selectedIndex == index and i == mid

		-- Offset from the current selected index
		local offset = mid - i

		local item = Roact.createElement("Frame", {
			LayoutOrder = i,
			BackgroundTransparency = 1,
			AutomaticSize = Enum.AutomaticSize.XY,
		}, {
			Roact.createElement(SurfaceArtSelectorItem, {
				image = self.props.images[index],
				isSelected = isSelected,
				transparency = self.getItemTransparency(i, index, mid),
				onClick = function()
					self.setCurrentIndex(index, offset)
				end,
			}),
		})

		items[self.formatTargetIndex(index, offset)] = item
	end

	local actionBarHeight = self.props.orientation.isPortrait and ACTION_BAR_HEIGHT_PORTRAIT
		or ACTION_BAR_HEIGHT_LANDSCAPE

	return Roact.createElement("Frame", {
		Size = UDim2.fromScale(1, 1),
		BackgroundTransparency = 1,
	}, {
		Background = Roact.createElement("Frame", {
			Size = UDim2.fromScale(1, 1),
			BackgroundColor3 = Color3.fromRGB(0, 0, 0),
			ZIndex = 1,
		}, {
			Gradient = Roact.createElement("UIGradient", {
				Transparency = NumberSequence.new({
					NumberSequenceKeypoint.new(0, 0),
					NumberSequenceKeypoint.new(0.2, 0.5),
					NumberSequenceKeypoint.new(0.8, 0.5),
					NumberSequenceKeypoint.new(1, 0),
				}),
				Rotation = self.props.orientation.isPortrait and 90 or 0,
			}),
		}),
		Container = Roact.createElement("Frame", {
			Size = UDim2.fromScale(1, 1),
			BackgroundTransparency = 1,
			ZIndex = 2,
		}, {
			Scroller = Roact.createElement("Frame", {
				Size = UDim2.new(1, 0, 1, -(actionBarHeight + ACTION_BAR_TOP_SPACING)),
				BackgroundTransparency = 1,
				Position = UDim2.fromScale(0.5, 0.5),
				AnchorPoint = Vector2.new(0.5, 0.5),
				ZIndex = 1,
			}, {
				UIListLayout = Roact.createElement("UIListLayout", {
					FillDirection = Enum.FillDirection.Horizontal,
					SortOrder = Enum.SortOrder.LayoutOrder,
				}),
				LeftButton = not self.useSinglePagination() and Roact.createElement(NavButton, {
					order = 1,
					image = self.props.configuration.leftArrowPageImage,
					onClick = self.prevPage,
					keyCode = self.props.configuration.usePageHotkeys and self.props.configuration.prevPageKey or nil,
				}),
				LeftSingleButton = Roact.createElement(NavButton, {
					order = 2,
					image = self.props.configuration.leftArrowItemImage,
					keyCode = self.props.configuration.usePageHotkeys and self.props.configuration.prevItemKey or nil,
					onClick = self.prevItem,
				}),
				Page = Roact.createElement("Frame", {
					LayoutOrder = 3,
					Size = self.useSinglePagination() and UDim2.fromScale(0.8, 1) or UDim2.fromScale(0.6, 1),
					BackgroundTransparency = 1,
					ClipsDescendants = true,
				}, {
					Container = Roact.createElement("Frame", {
						BackgroundTransparency = 1,
						Size = UDim2.fromScale(1, 1),
						AnchorPoint = Vector2.new(0.5, 0.5),
						Position = self.position:map(function(position)
							-- Calculate position for animation using pixel offset instead of scale.
							--
							-- This is because this Frame's size is not computed with all SurfaceArtSelectorItems rendered, but only
							-- those that are visible.
							return UDim2.new(0.5, position, 0.5, 0)
						end),
					}, items),
				}),
				RightSingleButton = Roact.createElement(NavButton, {
					order = 4,
					image = self.props.configuration.rightArrowItemImage,
					onClick = self.nextItem,
					keyCode = self.props.configuration.usePageHotkeys and self.props.configuration.nextItemKey or nil,
				}),
				RightButton = not self.useSinglePagination() and Roact.createElement(NavButton, {
					order = 5,
					image = self.props.configuration.rightArrowPageImage,
					onClick = self.nextPage,
					keyCode = self.props.configuration.usePageHotkeys and self.props.configuration.nextPageKey or nil,
				}),
			}),
			ActionBar = Roact.createElement("Frame", {
				Size = UDim2.new(1, 0, 0, actionBarHeight + ACTION_BAR_TOP_SPACING),
				BackgroundTransparency = 0.5,
				BackgroundColor3 = Color3.fromRGB(0, 0, 0),
				Position = UDim2.fromScale(0.5, 1),
				AnchorPoint = Vector2.new(0.5, 1),
				ZIndex = 3,
			}, {
				UIPadding = Roact.createElement("UIPadding", {
					PaddingTop = UDim.new(0, 16),
					PaddingBottom = UDim.new(0, 16),
				}),
				UIListLayout = Roact.createElement("UIListLayout", {
					SortOrder = Enum.SortOrder.LayoutOrder,
				}),
				TextLabel = Roact.createElement("TextLabel", {
					LayoutOrder = 1,
					Size = UDim2.fromScale(1, self.props.orientation.isPortrait and 0.5 or 0.4),
					BackgroundTransparency = 1,
					TextSize = 16,
					Font = Enum.Font.GothamSemibold,
					TextColor3 = Color3.fromRGB(255, 255, 255),
					TextYAlignment = Enum.TextYAlignment.Top,
					TextXAlignment = Enum.TextXAlignment.Center,
					TextWrapped = true,
					Text = string.format(
						"Choose a decal to place on the wall. You can add up to %d decals.",
						self.props.configuration.quotaPerPlayer
					),
				}, {
					UIPadding = Roact.createElement("UIPadding", {
						PaddingLeft = UDim.new(0, 8),
						PaddingRight = UDim.new(0, 8),
					}),
				}),
				Roact.createElement("Frame", {
					LayoutOrder = 2,
					Size = UDim2.fromScale(1, self.props.orientation.isPortrait and 0.5 or 0.6),
					BackgroundTransparency = 1,
				}, {
					ButtonGroup = Roact.createElement("Frame", {
						Size = UDim2.fromScale(0.5, 1),
						BackgroundTransparency = 1,
						Position = UDim2.fromScale(0.5, 0.5),
						AnchorPoint = Vector2.new(0.5, 0.5),
					}, {
						UIListLayout = Roact.createElement("UIListLayout", {
							FillDirection = Enum.FillDirection.Horizontal,
							SortOrder = Enum.SortOrder.LayoutOrder,
							Padding = UDim.new(0, 12),
						}),
						Cancel = Roact.createElement(Button, {
							LayoutOrder = 1,
							Text = "Cancel",
							TextColor3 = Color3.fromRGB(255, 255, 255),
							keyCode = Enum.KeyCode.B,
							onActivated = self.onCancel,
						}),
						Apply = Roact.createElement(Button, {
							LayoutOrder = 2,
							Text = "Apply",
							BackgroundColor3 = Color3.fromRGB(255, 255, 255),
							TextColor3 = Color3.fromRGB(0, 0, 0),
							keyCode = Enum.KeyCode.Return,
							onActivated = self.onApply,
						}),
					}),
				}),
			}),
		}),
	})
end

return ConfigurationContext.withConfiguration(OrientationContext.withOrientation(SurfaceArtSelector))