-- Custom Speed Mods v1.4
-- by AJ Kelly of KKI Labs
-- http://kki.ajworld.net/

--[[
changelog:

v1.4
* Try to auto-set the speed mod to 1.0 if:
 1) The player hasn't already chosen a speed mod
 2) The player's custom speed mod collection starts with a value under 1x.
 Due to the way the custom speed mods are coded, it will always pick the
 first value, even if it's not 1.0x.

v1.3
* strip whitespace out of file in case people use it.
	(I don't think it really works but SM seems to think the mods are legal)
* fixed an error related to using the fallback return value.

v1.2
* small fixes
* more comments

v1.1
* Cleaned up code some, I think.
]]

-- This code allows end users to add their own speed mods to the list.

-- Caveats:
--  * Still unsure if this will work if the theme is installed as a package.

function SpeedMods()
	-- GetSpeedMods() - read all the speed mods from a file.
	local function GetSpeedMods()
		local s = { };
		local file = RageFileUtil.CreateRageFile();
		
		-- the file is located at Data/SpeedMods.txt, meaning any other theme
		-- that reads custom speed mods in this location will use them.
		-- the root is the StepMania install directory.
		
		-- Currently unknown if you can get this to read from a memory card
		-- profile directory, much less a local profile directory.
		-- If you use Portable StepMania alpha 4+, you should be fine.
		local path = "Data/SpeedMods.txt"
		
		if file:Open(path, 1) then
			-- add each mod to the table. split by a comma.
			local a = file:Read();
			s = split(',',a);
			
			-- whitespace stripping
			-- I'm hoping this works for all spaces
			for i=1,#s do
				string.gsub(s[i], "%s", "");
			end
			
			file:destroy();
			return s;
		else
			-- couldn't be read for whatever reasons; write & return fallback
			Trace("[CustomSpeedMods]: Could not read SpeedMods; writing out fallback!");
			file:Open(path, 2);
			file:Write("0.5x,1x,1.5x,2x,3x,4x,8x,C200,C400");
			file:destroy();
			return {"0.5x","1x","1.5x","2x","3x","4x","8x","C200","C400"};
		end;
		-- this is unlikely but I am coding defensively
		Trace("[CustomSpeedMods]: unexpected jump location; using fallback!");
		return {"0.5x","1x","1.5x","2x","3x","4x","8x","C200","C400"};
	end;
	
	-- here we see the option menu itself.
	local t = {
		Name = "Speed",
		LayoutType = "ShowAllInRow",
		SelectType = "SelectOne",
		OneChoiceForAllPlayers = false,
		ExportOnChange = false,
		Choices = GetSpeedMods(),
		
		LoadSelections = function(self, list, pn)
			local pMods = GAMESTATE:GetPlayerState(pn):GetPlayerOptions("ModsLevel_Preferred");
			for i = 1,table.getn(self.Choices) do
				if string.find(pMods, self.Choices[i]) then
					list[i] = true;
					return;
				end;
			end;

			-- if we've reached this point, try to find 1x or 1.0x instead.
			for i = 1,table.getn(self.Choices) do
				if self.Choices[i] == "1x" or self.Choices[i] == "1.0x" then
					list[i] = true;
					return
				end;
			end;
		end,
		SaveSelections = function(self, list, pn)
			for i = 1,table.getn(self.Choices) do
				if list[i] then
					local PlayerState = GAMESTATE:GetPlayerState(pn);
					PlayerState:SetPlayerOptions("ModsLevel_Preferred",self.Choices[i]);
					return
				end
			end
		end
	};
	setmetatable( t, t );
	return t;
end;

--[[
Copyright © 2008 AJ Kelly/KKI Labs
Use freely.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
]]