-- 03 Gameplay.lua
-- ...is for fiddly mode-specific stuff, mainly, though there's some other fiddly
-- gameplay-affecting stuff here too.

-- Make it so some game modes force AutoSetStyle.
-- Practically a requirement in the TECHNO game mode, where all panel styles could be played in one round.
-- Enforced in the PARA game mode as it only has one unique style anyway.
function UsingAutoSetStyle()
	return GAMESTATE:GetCurrentGame():GetName() == "techno" or GAMESTATE:GetCurrentGame():GetName() == "para" or ThemePrefs.Get("AutoSetStyle")
end

-- I'm not in the mood to deal with GameplayMargins just yet, so here's a thing
function NotefieldPositioningHelper()
	local ratioStuff = (_screen.w / _screen.h) / 1.77
	
	return _screen.cx / (2 / ratioStuff)
end

-- todo: add toggle.
local XScale = true

-- The "boss song" threshold is based on the game mode,
-- and is something of a leftover from the "SMMAX" days.
-- A song with any chart rated above this threshold, even a chart outside the current game type(?),
-- will appear red on the song wheel. If an announcer is in use, it will use a "select music comment hard" line.
function GetExtraColorThreshold()
	local ret = {
		dance = XScale and 15 or 10,
		pump = 21,
		beat = 10,
		para = 7,
		popn = 45,
		techno = XScale and 15 or 10
	}
	return ret[GAMESTATE:GetCurrentGame():GetName()] or math.huge
end

-- The "ExtraStage2DifficultyMax" metric is also a partial leftover,
-- for deciding which song to force players to play should Encore Extra be reached.
-- It corresponds to the difficulty of CANDY[star] Expert/Heavy/Hard.
-- (However, before DDRX, the Doubles chart on the same difficulty was rated a 9)
function GetEncoreMaxDifficulty()
	local ret = {
		dance = XScale and 11 or 8,
		pump = 12,
		beat = 8,
		para = 5,
		popn = 38,
		techno = XScale and 11 or 8
	}
	return ret[GAMESTATE:GetCurrentGame():GetName()] or math.huge
end

-- These judgment-related things are also controlled by theme preferences,
-- but allow using the default gametype-based setting just in case.

-- Lowest judgment allowed to increment a combo.
function ComboContinue()
	local Continue = {
		dance = GAMESTATE:GetPlayMode() == "PlayMode_Oni" and "TapNoteScore_W2" or "TapNoteScore_W3",
		pump = "TapNoteScore_W3",
		beat = "TapNoteScore_W3",
		kb7 = "TapNoteScore_W3",
		para = "TapNoteScore_W3", -- change from W4, the judgments are different anyway
		ez2 = "TapNoteScore_W4"
	}
	if ThemePrefs.Get("CustomComboContinue") ~= "auto" then
		return ThemePrefs.Get("CustomComboContinue")
	else
		return Continue[GAMESTATE:GetCurrentGame():GetName()] or "TapNoteScore_W3"
	end
end

-- Lowest judgment allowed to maintain a combo; but not increment it.
function ComboMaintain()
	local Maintain = {
		dance = "TapNoteScore_W3",
		pump = "TapNoteScore_W4",
		beat = "TapNoteScore_W3",
		kb7 = "TapNoteScore_W3",
		para = "TapNoteScore_W3", -- change from W4, the judgments are different anyway
		ez2 = "TapNoteScore_W4"
	}
	local pref = ThemePrefs.Get("CustomComboMaintain")
	if pref ~= "auto" then
		return ThemePrefs.Get("CustomComboMaintain")
	else
		return Maintain[GAMESTATE:GetCurrentGame():GetName()] or "TapNoteScore_W3"
	end
end

--
function ComboPerRow()
	local returns = {
		pump = true,
		beat = true,
		para = true,
		popn = true
	}
	return returns[GAMESTATE:GetCurrentGame():GetName()] or GAMESTATE:GetPlayMode() == "PlayMode_Oni"
end

-- Merge Miss with the lowest available TNS in certain games.
function LowestTNSIsMiss()
	return GAMESTATE:GetCurrentGame():GetName() == "popn"
end

-- For "PARA" mode, merge O.K. and N.G. with the highest available TNS and Miss respectively.
function MergeHNSWithTNS()
	return GAMESTATE:GetCurrentGame():GetName() == "para"
end

-- Loading "Up" for noteskin previews in certain game types... eh, probably won't work so well.
-- Let's try to fix that.
function NoteForNoteSkinPreview()
	local returns = {
		pump = "UpLeft",
		beat = "Key1",
		ez2 = "HandUpLeft",
		maniax = "HandUpLeft",
		popn = "Red",
	}
	return returns[GAMESTATE:GetCurrentGame():GetName()] or "Up"
end

-- Making Metrics stuff translatable.
function GCString(text)
	return THEME:GetString("GCPieces", text)
end

-- Only allow players to join in the middle of an Event Mode game, or if no stages have been played yet (i.e. Taiko).
function AllowLateJoin()
	return (GAMESTATE:IsEventMode() or GAMESTATE:GetCurrentStage() == "Stage_1st")
end

-- Some game modes (like this theme's focus, para) only have one style anyway, so...
function ShowStepsTypeOnStepsList()
	return (ThemePrefs.Get("AutoSetStyle") and GAMESTATE:GetCurrentGame():GetName() ~= "para")
end

-- Here we go again...
-- A lot of the PARA mode codes aren't canon and are mostly made for "convenience"
-- on a 3-button setup (a real PPP cab or controller).
local CodeDetectorCodes = {
	-- steps
	PrevSteps1 = {
		default = "",
		dance = "Up,Up",
		pump = "+UpLeft",
		para = "Left,Left",
		popn = "+Left Yellow",
	},
	PrevSteps2 = {
		default = "MenuUp",
		dance = "MenuUp,MenuUp",
		pump = "",
	},
	NextSteps1 = {
		default = "",
		dance = "Down,Down",
		pump = "+UpRight",
		para = "Right,Right",
		popn = "+Right Yellow",
	},
	NextSteps2 = {
		default = "MenuDown",
		dance = "MenuDown,MenuDown",
		pump = "",
	},
	-- group
	NextGroup = {
		default = "",
		dance = "MenuUp,MenuRight,MenuRight",
		pump = "",
		popn = "+Right White",
	},
	PrevGroup = {
		default = "",
		dance = "MenuUp,MenuDown,MenuUp,MenuDown",
		pump = "",
		popn = "+Left White",
	},
	CloseCurrentFolder = {
		default = "MenuUp-MenuDown",
	},
	-- sorts
	NextSort1 = {
		default = "",
		dance = "@MenuLeft-@MenuRight-Start",
		pump = "@MenuLeft-@MenuRight-Start",
	},
	NextSort2 = {
		default = "",
		dance = "MenuLeft-MenuRight",
		pump = "MenuLeft-MenuRight",
	},
	NextSort3 = {
		default = "",
		dance = "@Left-@Right-Start",
		pump = "@DownLeft-@DownRight-Start",
	},
	NextSort4 = {
		default = "",
		dance = "Left-Right",
		pump = "DownLeft-DownRight",
	},
	-- modemenu
	ModeMenu1 = {
		default = "@MenuLeft-@MenuRight-Start",
		dance = "Up,Down,Up,Down",
	},
	ModeMenu2 = {
		default = "MenuUp,MenuDown,MenuUp,MenuDown",
	},
	-- Evaluation:
	SaveScreenshot1 = {
		default = "MenuLeft-MenuRight",
	},
	SaveScreenshot2 = {
		default = "Select",
	},
	-- modifiers section
	CancelAll = {
		default = "",
		dance = "Left,Right,Left,Right,Left,Right,Left,Right",
	},
	--- specific modifiers
	Mirror = {
		default = "",
		dance = "",
		pump = "DownRight,DownLeft,UpRight,UpLeft,DownRight,DownLeft,UpRight,UpLeft,Center",
	},
	Left = {
		default = "",
		dance = "",
	},
	Right = {
		default = "",
		dance = "",
	},
	Shuffle = {
		default = "",
		dance = "",
		pump = "UpLeft,UpRight,UpLeft,UpRight,DownLeft,DownRight,DownLeft,DownRight,Center", -- random
	},
	SuperShuffle = {
		default = "",
		dance = "",
		pump = "UpLeft,UpRight,DownLeft,DownRight,UpLeft,UpRight,DownLeft,DownRight,Center"
	},
	Reverse = {
		default = "",
		dance = "",
		pump = "UpLeft,DownLeft,UpRight,DownRight,UpLeft,DownLeft,UpRight,DownRight,DownRight", -- drop
	},
	HoldNotes = {
		default = "",
		dance = "",
	},
	Mines = {
		default = "",
	},
	Dark = {
		default = "",
	},
	Hidden = {
		default = "",
		pump = "UpLeft,UpRight,DownLeft,DownRight,Center", -- vanish
	},
	RandomVanish = {
		default = "",
	},
	-- boost (accel), brake (decel), stealth (nonstep)
	--- next/prev modifiers
	NextTransform = {
		default = "",
	},
	NextScrollSpeed = {
		default = "",
		dance = "",
		pump = "UpLeft,UpRight,UpLeft,UpRight,Center",
	},
	PreviousScrollSpeed = {
		default = "",
		dance = "",
		pump = "UpRight,UpLeft,UpRight,UpLeft,Center",
	},
	NextAccel = {
		default = "",
		dance = "",
	},
	NextEffect = {
		default = "",
		dance = "",
	},
	NextAppearance = {
		default = "",
		dance = "",
	},
	NextTurn = {
		default = "",
	},
	-- cancel all in player options
	CancelAllPlayerOptions = {
		default = "",
		dance = "Left,Right,Left,Right,Left,Right",
	},
	-- Code detection (particularly for NameEntryTraditional) doesn't play nice with game buttons...
	NavLeft = {
		dance = "+Left",
		pump = "+DownLeft"
	},
	NavRight = {
		dance = "+Right",
		pump = "+DownRight"
	},
	NavUp = {
		dance = "+Up",
		pump = "+UpLeft"
	},
	NavDown = {
		dance = "+Down",
		pump = "+UpRight"
	},
	NavStart = {
		pump = "Center"
	},
	PrevOptionsList = {
		default = "@MenuUp-MenuDown",
	},
	NextOptionsList = {
		default = "@MenuDown-MenuUp",
	},
	-- 
	OpenOptionsList = {
		default = "",
		para = "Up,Up"
	}
}

-- RAGEY
function GetCodeForGame(codeName)
	local gameName = string.lower(GAMESTATE:GetCurrentGame():GetName())
	local inputCode = CodeDetectorCodes[codeName]
	return (inputCode[gameName] or inputCode["default"]) or ""
end
