--local cardWidth = _screen.w / 2.9
local cardWidth = 294

function GetLocalProfiles(alsoPN)
	local pnMod = alsoPN == PLAYER_1
	local t = {}

	function GetSongsPlayedString(numSongs)
		return numSongs == 1 and Screen.String("SingularSongPlayed") or Screen.String("SeveralSongsPlayed")
	end

	for p = 0,PROFILEMAN:GetNumLocalProfiles()-1 do
		local profile=PROFILEMAN:GetLocalProfileFromIndex(p)
		local ProfileCard = Def.ActorFrame {
			LoadActor("pTag") .. {
				OnCommand=function(self)
					self:horizalign(pnMod and right or left):x(pnMod and cardWidth/2 or -cardWidth/2)
				end
			},
			LoadActor("pAv") .. {
				OnCommand=function(self)
					self:diffuse(PlayerColor(alsoPN)):horizalign(left):x(pnMod and -cardWidth/2 or cardWidth/2):rotationz(pnMod and 0 or 180)
				end
			},
			LoadFont("Common Normal") .. {
				Text=profile:GetDisplayName(),
				OnCommand=function(self)
					self:horizalign(pnMod and left or right):shadowlength(1):xy(pnMod and (-cardWidth/2)+62 or (cardWidth/2)-62,-6):zoom(0.8):maxwidth(cardWidth)
				end
			},
			LoadFont("Common Normal") .. {
				InitCommand=cmd(shadowlength,1;y,12;zoom,0.4;vertspacing,-8;maxwidth,cardWidth),
				BeginCommand=function(self)
					local numSongsPlayed = profile:GetNumTotalSongsPlayed()
					self:settext( string.format( GetSongsPlayedString( numSongsPlayed ), numSongsPlayed ) )
					self:horizalign(pnMod and left or right):x(pnMod and (-cardWidth/2)+62 or (cardWidth/2)-62)
				end
			},
			Def.Sprite{
				Texture=LoadModule("Options.GetProfileData.lua")(p,true)["Image"];
				InitCommand=function(self)
					self:setsize(50,50):horizalign(pnMod and left or right):x(pnMod and (-cardWidth/2)+5 or (cardWidth/2)-5)
					--self:ztest(true)
				end
			}
		}
		t[#t+1]=ProfileCard
	end

	return t
end

function LoadCard(cColor)
	return Def.Quad {
		InitCommand=cmd(zoomto,cardWidth,SCREEN_HEIGHT/1.3;diffuse,ColorDarkTone(cColor);diffusealpha,0.6;fadetop,0.3;fadebottom,0.3)
	}
end

function LoadPlayerStuff(Player)
	local pn = (Player == PLAYER_1) and 1 or 2

	local t = Def.ActorFrame {
		Def.ActorFrame {
			Name = 'BigFrame',
			Def.Quad {
				OnCommand=function(self)
					self:zoomto(cardWidth,SCREEN_HEIGHT/1.15):diffuse(Color.Black):diffusealpha(0.75):faderight(pn == 1 and 0.2 or 0):fadeleft(pn == 1 and 0 or 0.2)
				end
			},
			LoadActor(THEME:GetPathG("_common", "bigneon")) .. {
				OnCommand=function(self)
					self:x(pn == 2 and -cardWidth/2 or cardWidth/2):rotationz(90):vertalign(pn == 2 and bottom or top):zoomto(SCREEN_HEIGHT/1.15,10):diffuse(PlayerColor(Player)):blend(Blend.Add)
				end
			},
			LoadActor(THEME:GetPathG("_common", "bigneon")) .. {
				OnCommand=function(self)
					self:x(pn == 1 and (-cardWidth/2)-10 or (cardWidth/2)+10):rotationz(90):vertalign(pn == 1 and bottom or top):zoomto(SCREEN_HEIGHT/1.15,10):diffuse(PlayerColor(Player)):blend(Blend.Add)
				end
			}
		},
		Def.ActorFrame {
			Name = 'SmallFrame',
			LoadActor("selFrame") .. {
				--InitCommand=cmd(zoomto,cardWidth,40),
				--OnCommand=cmd(diffuse,Color.Alpha(PlayerColor(Player), 0.4))
				OnCommand=function(self)
					self:rotationz(pn == 1 and 0 or 180):xy(pn == 1 and 20*0.9 or -20*0.9,-24):zoom(0.9)
				end
			}
		},

		Def.ActorScroller{
			Name = 'Scroller',
			NumItemsToDraw=8,
			InitCommand=cmd(xy,pn == 1 and -10 or 10,-24);
			OnCommand=cmd(SetFastCatchup,true;SetMask,200,58;SetSecondsPerItem,0.15),
			OffCommand=cmd(decelerate,0.5;diffusealpha,0),
			TransformFunction=function(self, offset, itemIndex, numItems)
				local focus = scale(math.abs(offset),0,2,1,0)
				self:visible(false)
				self:y(math.floor( offset*60 )):zoom(0.9)
			end,
			children = GetLocalProfiles(Player)
		},
		
		LoadActor("nameTag") .. {
			Name = "NameTag",
			OnCommand=function(self)
				self:xy(pn == 1 and -5 or 5,_screen.cy-18):vertalign(bottom):diffuse(PlayerColor(Player)):zoomx(pn == 1 and 1 or -1)
			end
		},
		
		LoadFont("Common BEEG") .. {
			Text = ToEnumShortString(Player),
			OnCommand=function(self)
				self:horizalign(pn == 1 and left or right):xy(pn == 1 and (-cardWidth/2) or (cardWidth/2),_screen.cy-56):
					zoom(0.6):strokecolor(Color.Outline)
			end
		},
		
		LoadFont("Common Normal") .. {
			Name = 'SelectedProfileText',
			OnCommand=function(self)
				self:horizalign(pn == 1 and left or right):xy(pn == 1 and (-cardWidth/2)+70 or (cardWidth/2)-70,_screen.cy-56):strokecolor(Color.Black):zoom(0.75):maxwidth(208/0.75)
			end
		},
		
		Def.ActorFrame {
			Name = 'JoinFrame',
			LoadFont("Common Normal") .. {
				Text="Press &START; to join!",
				OnCommand=function(self)
					self:horizalign(pn == 1 and left or right):xy(pn == 1 and (-cardWidth/2)+70 or (cardWidth/2)-70,_screen.cy-56):strokecolor(Color.Black):zoom(0.75):maxwidth(208/0.75):glowblink():effectcolor1(Color.Invisible):effectcolor2(Color.White)
				end
			}
		},
	}

	return t
end

-- here's a (messy) fix for one player's selection ending the screen,
-- at least until this whole thing is rewritten to be... Not this
local ready = {}
local function AllPlayersReady()
	for i, pn in ipairs(GAMESTATE:GetHumanPlayers()) do
		if not ready[pn] then
			return false
		end
	end
	-- if it hasn't returned false by now, surely it must be true, right? RIGHT???
	return true
end

function UpdateInternal3(self, Player)
	local pn = (Player == PLAYER_1) and 1 or 2
	local frame = self:GetChild(string.format('P%uFrame', pn))
	local scroller = frame:GetChild('Scroller')
	local seltext = frame:GetChild('SelectedProfileText')
	local joinframe = frame:GetChild('JoinFrame')
	local smallframe = frame:GetChild('SmallFrame')
	local bigframe = frame:GetChild('BigFrame')
	local namTag = frame:GetChild('NameTag')

	if GAMESTATE:IsHumanPlayer(Player) then
		frame:visible(true)
		namTag:diffuse(PlayerColor(Player))
		if MEMCARDMAN:GetCardState(Player) == 'MemoryCardState_none' then
			--using profile if any
			joinframe:visible(false)
			smallframe:visible(not ready[Player])
			bigframe:visible(true)
			seltext:visible(true)
			scroller:visible(not ready[Player])
			local ind = SCREENMAN:GetTopScreen():GetProfileIndex(Player)
			if ind > 0 then
				scroller:SetDestinationItem(ind-1)
				seltext:settext(PROFILEMAN:GetLocalProfileFromIndex(ind-1):GetDisplayName())
			else
				if SCREENMAN:GetTopScreen():SetProfileIndex(Player, 1) then
					scroller:SetDestinationItem(0)
					self:queuecommand('UpdateInternal2')
				else
					joinframe:visible(true)
					smallframe:visible(false)
					bigframe:visible(false)
					scroller:visible(false)
					seltext:settext('No profile')
				end
			end
		else
			--using card
			smallframe:visible(false)
			scroller:visible(false)
			seltext:settext('External profile')
			SCREENMAN:GetTopScreen():SetProfileIndex(Player, 0)
		end;
	else
		namTag:diffuse(ColorBlend(PlayerColor(Player), Color.Black))
		joinframe:visible(true)
		scroller:visible(false)
		seltext:visible(false)
		smallframe:visible(false)
		bigframe:visible(false)
	end
end

local t = Def.ActorFrame {

	StorageDevicesChangedMessageCommand=function(self, params)
		self:queuecommand('UpdateInternal2')
	end,

	CodeMessageCommand = function(self, params)
		if params.Name == 'Start' or params.Name == 'Center' then
			-- Only you can prevent noise spamming.
			if not ready[params.PlayerNumber] then
				SCREENMAN:PlayStartSound()
			end
			
			if not GAMESTATE:IsHumanPlayer(params.PlayerNumber) then
				SCREENMAN:GetTopScreen():SetProfileIndex(params.PlayerNumber, -1)
			else
				ready[params.PlayerNumber] = true
				if AllPlayersReady() then
					SCREENMAN:GetTopScreen():Finish()
				end
			end
			self:queuecommand('UpdateInternal2') --Just in case.
		end
		if params.Name == 'Up' or params.Name == 'Up2' or params.Name == 'Up3' or params.Name == 'Up4' or params.Name == 'DownLeft' then
			-- Added a line to make sure the player can't fiddle around in the menu
			-- after they've already made a selection.
			if GAMESTATE:IsHumanPlayer(params.PlayerNumber) and not ready[params.PlayerNumber] then
				local ind = SCREENMAN:GetTopScreen():GetProfileIndex(params.PlayerNumber)
				if ind > 1 then
					if SCREENMAN:GetTopScreen():SetProfileIndex(params.PlayerNumber, ind - 1 ) then
						MESSAGEMAN:Broadcast("DirectionButton")
						self:queuecommand('UpdateInternal2')
					end
				end
			end
		end
		if params.Name == 'Down' or params.Name == 'Down2' or params.Name == 'Down3' or params.Name == 'Down4' or params.Name == 'DownRight' then
			if GAMESTATE:IsHumanPlayer(params.PlayerNumber) and not ready[params.PlayerNumber] then
				local ind = SCREENMAN:GetTopScreen():GetProfileIndex(params.PlayerNumber)
				if ind > 0 then
					if SCREENMAN:GetTopScreen():SetProfileIndex(params.PlayerNumber, ind + 1 ) then
						MESSAGEMAN:Broadcast("DirectionButton")
						self:queuecommand('UpdateInternal2')
					end
				end
			end
		end
		if params.Name == 'Back' then
			if GAMESTATE:GetNumPlayersEnabled()==0 then
				SCREENMAN:GetTopScreen():Cancel()
			else
				if GAMESTATE:IsHumanPlayer(params.PlayerNumber) then
					SCREENMAN:PlayCancelSound()
				end
				-- Allow... erm... un-readying a player.
				if ready[params.PlayerNumber] then
					ready[params.PlayerNumber] = false
				else
					SCREENMAN:GetTopScreen():SetProfileIndex(params.PlayerNumber, -2)
				end
			end
			self:queuecommand('UpdateInternal2') --Just in case.
		end
	end,

	PlayerJoinedMessageCommand=function(self, params)
		self:queuecommand('UpdateInternal2')
	end,

	PlayerUnjoinedMessageCommand=function(self, params)
		self:queuecommand('UpdateInternal2')
	end,

	OnCommand=function(self, params)
		self:queuecommand('UpdateInternal2')
	end,

	UpdateInternal2Command=function(self)
		UpdateInternal3(self, PLAYER_1)
		UpdateInternal3(self, PLAYER_2)
	end,

	Def.ActorFrame {
		Name = 'P1Frame',
		InitCommand=cmd(x,SCREEN_CENTER_X-160;y,SCREEN_CENTER_Y),
		--OnCommand=cmd(zoom,0;bounceend,0.35;zoom,1);
		OffCommand=cmd(decelerate,0.3;diffusealpha,0),
		-- PlayerJoinedMessageCommand=function(self,param)
			-- if param.Player == PLAYER_1 then
				-- (cmd(;zoom,1.15;bounceend,0.175;zoom,1.0;))(self);
			-- end;
		-- end;
		children = LoadPlayerStuff(PLAYER_1),
	},
	Def.ActorFrame {
		Name = 'P2Frame',
		InitCommand=cmd(x,SCREEN_CENTER_X+160;y,SCREEN_CENTER_Y),
		--OnCommand=cmd(zoom,0;bounceend,0.35;zoom,1);
		OffCommand=cmd(decelerate,0.3;diffusealpha,0),
		-- PlayerJoinedMessageCommand=function(self,param)
			-- if param.Player == PLAYER_2 then
				-- (cmd(zoom,1.15;bounceend,0.175;zoom,1.0;))(self);
			-- end;
		-- end;
		children = LoadPlayerStuff(PLAYER_2)
	},
	-- We don't particularly... Need to load sound actors.
	-- Using this method caused the Start sound to cut off when the screen transitioned
	LoadActor( THEME:GetPathS("Common","value") )..{
		DirectionButtonMessageCommand=cmd(play)
	}
}

return t
