-- This will discuss how to create an option row in lua for use on a normal options screen.

-- To try out this example, copy this file to Scripts/ and add the following
-- line to metrics.ini, on one of the options screens.  Change the "1" to an
-- appropriate line name and make sure it's in the LineNames list for that
-- screen.
-- Line1="lua,FooMods()"

-- Make sure you test this with Player 2, Player 1 can't interact with this
-- option row as part of the example.
-- When on the screen testing the example, flush the log and read it when
-- interacting with the option row.  This example doesn't actually apply any
-- modifiers to the player, it just prints messages to the log file so you can
-- see what functions are being called.

-- Comments explaining an element come before the element they explain.

-- The function "FooMods" returns a table containing all the information the
-- option row handler needs to build the option row.
function FooMods()
	return {
		-- A string with the name of the row.  This name will be localized using
		-- the entry in the "OptionTitles" section of the language file.
		Name= "Foo",

		-- A boolean that controls whether this row goes to the "next row"
		-- element when NavigationMode for the screen is "toggle" and the
		-- ArcadeOptionsNavigation preference is 1.
		GoToFirstOnStart= false,

		-- A boolean controlling whether the choice affects all players.
		OneChoiceForAllPlayers= false,

		-- A boolean controlling whether SaveSelections is called after every
		-- change.  If this is true, SaveSelections will be called every time
		-- the player moves the cursor on the row.
		ExportOnChange= false,

		-- A LayoutType enum value.  "ShowAllInRow" shows all items in the row,
		-- "ShowOneInRow" shows only the choice with focus is shown.
		-- "ShowOneInRow" is forced if there are enough choices that they would go
		-- off screen.
		LayoutType= "ShowAllInRow",

		-- A SelectType enum value.  "SelectOne" allows only one choice to be
		-- selected.  "SelectMultiple" allows multiple to be selected.
		-- "SelectNone" allows none to be selected.
		SelectType= "SelectMultiple",

		-- Optional function.  If non-nil, this function must return a table of
		-- PlayerNumbers that are allowed to use the row.
		-- A row that can't be used by one player can be confusing for the players
		-- so consider carefully before using this.
		-- This function will be called an extra time during loading to ensure
		-- it returns a table.
		EnabledForPlayers= function(self)
			Trace("FooMods:EnabledForPlayers() called.")
			-- Leave out PLAYER_1 just for example.
			return {PLAYER_2}
		end,

		-- Optional function. If non-nil, this function must return the string representation
		-- of a member of the ReloadChanged enum. This function is called in response to a message
		-- listed in the optional ReloadRowMessages table below. For example,
		-- to completely change the Choices presented by this OptionRow, modify
		-- self.Choices in the body of this function and return "ReloadChanged_All"
		Reload= function(self)
			Trace("FooMods:Reload() called.")
			return "ReloadChanged_None"
		end,

		-- A table of strings that are the names of choices.  Choice names are not
		-- localized.
		Choices= {"a", "b", "c", "d"},

		-- Optional table.  If non-nil, this table must contain a list of messages
		-- this row should listen for.  If one of the messages is recieved, the
		-- row is reloaded (and each of the EnabledForPlayers/Reload functions is called if it is
		-- non-nil).
		ReloadRowMessages= {"ReloadFooMods"},

		-- LoadSelections should examine the player and figure out which options
		-- on the row the player has selected.
		-- self is the table returned by the original function used to create the
		-- option row. (the table being created right now).
		-- list is a table of bools, all initially false.  Set them to true to
		-- indicate which options are on.
		-- pn is the PlayerNumber of the player the selections are for.
		LoadSelections= function(self, list, pn)
			Trace("FooMods:LoadSelections(" .. pn .. ")")
			for i, choice in ipairs(self.Choices) do
				-- Randomly set some to true just for an example.
				if math.random(0, 1) == 1 then
					Trace(choice .. " (" .. i .. ")" .. " set to true.")
					list[i]= true
				end
			end
		end,

		-- SaveSelections should examine the list of what the player has selected
		-- and apply the appropriate modifiers to the player.
		-- Same args as LoadSelections.
		--
		-- May optionally return an "effects" bit mask (constructed by combination of
		-- the bit masks from the OptEffect enum), which dictates actions the
		-- game should take in response to the selected option. For example,
		-- OPT_SAVE_PREFERENCES directs the game to save Preferences.ini,
		-- OPT_APPLY_ASPECT_RATIO directs the game to recompute the projection matrix, etc.
		SaveSelections= function(self, list, pn)
			Trace("FooMods:SaveSelections(" .. pn .. ")")
			for i, choice in ipairs(self.Choices) do
				if list[i] then
					Trace(choice .. " (" .. i .. ")" .. " set to true.")
				end
			end
		end,

		-- Optional function.  If non-nil, this function must take 3 parameters
		-- (self, pn, choice), and return a bool.  It is called when a player
		-- selects an item in the row by pressing start.
		-- self is the same as for LoadSelections.
		-- pn is the PlayerNumber of the player that made the selection.
		-- choice is the choice the player's cursor is on.
		-- The return value should be true if the Choices table is changed.  If it
		-- is true, then LoadSelections will be called to update which choices are
		-- underlined for each player.
		-- This function is meant to provide a way for a menu to change the text of
		-- its choices.  If it returns true, LoadSelections will be called for each
		-- player.  If OneChoiceForAllPlayers is true, this function will be called
		-- for each player, which means LoadSelections will be called twice for
		-- each player.  Well written code shouldn't have a problem with this.
		NotifyOfSelection= function(self, pn, choice)
			Trace("FooMods:NotifyOfSelection(" .. pn .. ", " .. choice .. ")")
			-- Randomly decide whether to change, as an example.
			local change= math.random(0, 3)
			-- No change half the time, lengthen or clip strings the other half.
			if change < 2 then
				Trace("Not changing choices.")
			else
				Trace("Changing choices.")
			end
			if change == 2 then
				for i, choice in ipairs(self.Choices) do
					self.Choices[i]= choice .. choice
				end
			elseif change == 3 then
				for i, choice in ipairs(self.Choices) do
					self.Choices[i]= choice:sub(1, 1)
				end
			end
			-- Don't actually broadcast a reload message from here, do it from some
			-- other place that actually has a reason to trigger a reload.  This is
			-- just here so that nothing needs to be added to a screen's lua files
			-- for this example.
			if math.random(0, 5) == 0 then
				Trace("Broadcasting reload message.")
				MESSAGEMAN:Broadcast("ReloadFooMods")
			end
			return change >= 2
		end
	}
end
