local t = Def.ActorFrame {
	--Def.ControllerStateDisplay {
	--	InitCommand=cmd(LoadGameController,
	--};
	Def.BitmapText {
		Text=THEME:GetString("ScreenTestInput", "ConnectedDevices"),
		Font="Common Normal",
		OnCommand=function(self) self:zoom(0.75):horizalign(left):xy(20,50):strokecolor(Color.Black) end
	},
	Def.DeviceList {
		Font="Common Normal",
		InitCommand=cmd(x,20;y,70;halign,0;vertalign,top;zoom,0.6;strokecolor,Color.Outline);
	},
	
	Def.BitmapText {
		Text=THEME:GetString("ScreenTestInput", "AnalogTracking"),
		Font="Common Normal",
		OnCommand=function(self) self:zoom(0.75):horizalign(right):xy(_screen.w-20,50):strokecolor(Color.Black) end
	},
	Def.BitmapText {
		Text=THEME:GetString("ScreenTestInput", "AnalogNoInput"),
		Font="Common Normal",
		OnCommand=function(self) self:xy(_screen.w-20,70):zoom(0.6):horizalign(right):vertalign(top):strokecolor(Color.Outline) end,
		AnalogInputMessageCommand=function(self,Params)
			if Params.Value > 0.01 or Params.Value < -0.01 then
				self:settext("Device: "..Params.Device.."\nButton"..Params.Button.."\nValue:"..Params.Value)
			else
				self:settext(THEME:GetString("ScreenTestInput", "AnalogNoInput"))
			end
		end
	},
	
	-- ExplanationTogether lookalike.
	-- Def.BitmapText{
		-- Font="Common Normal",
		-- OnCommand=cmd(xy,_screen.cx,_screen.h-56;zoom,0.4;shadowlength,0;wrapwidthpixels,_screen.w/0.44;playcommand,"UpdateBlebText"),
		-- UpdateBlebTextCommand=function(self)
			-- self:settext(THEME:GetString("ScreenTestInput", "Explanation")):stoptweening():cropright(1):linear(0.5):cropright(0)
		-- end
	-- },
}

-- This is where the fun begins
local held = {}

-- Nab the key bindings.
local keyBinds = FILEMAN:DoesFileExist("Save/Keymaps.ini") and IniFile.ReadFile("Save/Keymaps.ini")[GAMESTATE:GetCurrentGame():GetName()] or {}

local notMapped = {}

local function InputHandler( event )
	if event.PlayerNumber and event.button then
		if event.type == "InputEventType_FirstPress" then
			held[event.PlayerNumber][event.button] = true
		elseif event.type == "InputEventType_Release" then
			held[event.PlayerNumber][event.button] = false
		end
	end
end

local playArea = Def.ActorFrame{
	OnCommand = function(self)
		SCREENMAN:GetTopScreen():AddInputCallback( InputHandler )
		self:fov(45):rotationx(-55):y(_screen.h-110)
	end,
	
	-- Floor? (I'm putting too much effort into making this look pretty)
	Def.Quad {
		Name = "pattern",
		OnCommand=function(self)
			self:xy(_screen.cx,_screen.cy/1.5):vertalign(bottom):zoomto(_screen.w+300,380):diffuse(LocalBlueColor(0)):fadetop(0.7)
		end
	},
	LoadActor(THEME:GetPathB("_common", "halftone")) .. {
		Name = "pattern",
		OnCommand=function(self)
			self:xy(_screen.cx,_screen.cy/1.5):vertalign(bottom):zoomto(_screen.w+300,380):customtexturerect(0,0,(_screen.w+300)/512,380/512):diffuse(Color.Outline)
		end
	},
}

local portionSize = 80
-- Vertex positions to make decorations with later.
local octo = {
	{{-1,-1,0}, Color.White}, -- topleft
	{{0,-1.4,0}, Color.White},	--
	{{1,-1,0}, Color.White},	-- topright
	{{1.4,0,0}, Color.White},	-- 
	{{1,1,0}, Color.White}, -- bottomright
	{{0,1.4,0}, Color.White},	--
	{{-1,1,0}, Color.White},	-- bottomleft
	{{-1.4,0,0}, Color.White},	--
	{{-1,-1,0}, Color.White},	-- back to topleft	
}

for player in ivalues({PLAYER_1, PLAYER_2}) do
	held[player] = {}
	notMapped[player] = {}
	
	--oof
	local onlyN = player == PLAYER_1 and "1" or "2"
	
	--TODO: other game modes?
	local arrowTable = {
		-- {Name, X, Y, Z}
		{"Left", -portionSize, 0, 0},
		{"UpLeft", -portionSize*0.725, -portionSize*0.725, 0},
		{"Up", 0, -portionSize, 0},
		{"UpRight", portionSize*0.725, -portionSize*0.725, 0},
		{"Right", portionSize, 0, 0},
	}
	
	local function Update(self, deltaTime)
		for i,Ar in ipairs(arrowTable) do
			if held[player][Ar[1]] then
				self:GetChild(Ar[1]):GetChild("Bom"):visible(true)
			else
				self:GetChild(Ar[1]):GetChild("Bom"):visible(false)
			end
		end
	end
	
	local playerThing = Def.ActorFrame{
		Name = player,
		InitCommand=function(self)
			self:SetUpdateFunction(Update)
		end,
		OnCommand=function(self)
			self:x(player == PLAYER_1 and _screen.cx-(portionSize*1.5) or _screen.cx+(portionSize*1.5)):zoom(1)
		end,
		
		-- Base! hwhaha
		Def.ActorMultiVertex{
			OnCommand=function(self)
				self:zoomto(portionSize,portionSize):diffuse(PlayerColor(player))
				
				self:SetNumVertices(#octo):SetLineWidth(2):SetDrawState({Mode="DrawMode_LineStrip",First=1,Num=-1})
				self:SetVertices(1, octo)
			end
		},
		Def.ActorMultiVertex{
			OnCommand=function(self)
				self:zoomto(portionSize,portionSize):diffuse(PlayerColor(player)):diffusealpha(0.5)
				
				self:SetNumVertices(#octo):SetLineWidth(3):SetDrawState({Mode="DrawMode_Fan",First=1,Num=-1})
				self:SetVertices(1, octo)
			end
		},
		Def.ActorMultiVertex{
			OnCommand=function(self)
				self:zoomto(portionSize*0.45,portionSize*0.45):diffuse(PlayerColor(player)):diffusealpha(0.5)
				
				self:SetNumVertices(#octo):SetLineWidth(3):SetDrawState({Mode="DrawMode_Fan",First=1,Num=-1})
				self:SetVertices(1, octo)
			end
		},
	}
	
	for i,Ar in ipairs(arrowTable) do
		playerThing[#playerThing+1] = Def.ActorFrame {
			Name = Ar[1],
			OnCommand=function(self)
				self:xy(Ar[2], Ar[3]):z(Ar[4])
			end,
			Def.ActorMultiVertex{
				OnCommand=function(self)
					self:zoomto(portionSize*0.25,portionSize*0.25):diffuse(PlayerColor(player))
					
					-- When a bvtton isn't mapped
					local theBind = keyBinds[onlyN .. "_" .. Ar[1]]
					if theBind == "" then
						self:diffuse(Color.Black):diffusealpha(0.5)
						notMapped[player][Ar[1]] = true
					end
					
					self:SetNumVertices(#octo):SetLineWidth(3):SetDrawState({Mode="DrawMode_Fan",First=1,Num=-1})
					self:SetVertices(1, octo)
				end
			},
			NOTESKIN:LoadActorForNoteSkin(Ar[1], "Receptor", GAMESTATE:GetPlayerState(GAMESTATE:GetMasterPlayerNumber()):GetPlayerOptions('ModsLevel_Current'):NoteSkin()) .. {
				OnCommand=function(self) self:diffusealpha(0.25) end
			},
			NOTESKIN:LoadActorForNoteSkin(Ar[1], "Tap Note", GAMESTATE:GetPlayerState(GAMESTATE:GetMasterPlayerNumber()):GetPlayerOptions('ModsLevel_Current'):NoteSkin()) .. {
				Name = "Bom"
			},
		}
	end
	
	playArea[#playArea+1] = playerThing
end

t[#t+1] = playArea

-- Need to put this last because of layering issues.
t[#t+1] = Def.InputList {
	Font="Common Normal",
	InitCommand=cmd(xy,_screen.cx,_screen.cy*1.1;zoom,0.75;vertspacing,8;strokecolor,Color.Outline)
}

t[#t+1] = Def.BitmapText{
	Font = "Common Normal",
	Text = THEME:GetString("ScreenTestInput", "ButtonsNotMapped"),
	OnCommand=function(self)
		self:xy(_screen.cx,_screen.h-60):zoom(0.5):maxwidth(_screen.w/0.5):strokecolor(Color.Black):shadowlengthy(2)
		for i,mlem in ipairs(notMapped) do
			if #mlem > 0 then self:visible(true) break end
			self:visible(false)
		end
	end
}

return t