local function Autogen(pn)
	local function set(self, player)
		if player and player ~= pn then return end
		local Selection = GAMESTATE:GetCurrentSteps(pn) or GAMESTATE:GetCurrentCourse()
		local bIsAutogen = Selection and Selection:IsAutogen();
		self:visible( bIsAutogen and true or false );
	end

	local t = LoadActor( "_autogen" ) .. {
		OnCommand=cmd(zoomy,0;linear,0.5;zoomy,1);
		OffCommand=cmd(linear,0.5;zoomy,0);
		CurrentStepsP1ChangedMessageCommand=function(self) set(self, PLAYER_1); end;
		CurrentStepsP2ChangedMessageCommand=function(self) set(self, PLAYER_2); end;
		CurrentCourseChangedMessageCommand=function(self) set(self); end;
	};
	return t;
end

local function DifficultyMeter(pn)
	local function set(self, player)
		self:SetFromGameState( player );
	end

	local t = Def.DifficultyMeter {
		Type="DifficultyMeter"; -- metrics section
	};

	if pn == PLAYER_1 then
		t.CurrentStepsP1ChangedMessageCommand=function(self) set(self, pn); end;
		t.CurrentTrailP1ChangedMessageCommand=function(self) set(self, pn); end;
	else
		t.CurrentStepsP2ChangedMessageCommand=function(self) set(self, pn); end;
		t.CurrentTrailP2ChangedMessageCommand=function(self) set(self, pn); end;
	end

	return t;
end

local t = Def.ActorFrame {

	-- banner section
	Def.ActorFrame{
		Name="BannerSection";
		InitCommand=cmd(x,SCREEN_CENTER_X-172;y,SCREEN_CENTER_Y-32);
		
		Def.ActorProxy {
			BeginCommand=function(self) local banner = SCREENMAN:GetTopScreen():GetChild('Banner'); self:SetTarget(banner); end;
			OffCommand=cmd(linear,0.2;diffusealpha,0);
		};
		
		LoadActor( "_banner frame" ) .. {
			InitCommand=cmd(diffusealpha,0);
			OnCommand=cmd(linear,0.2;diffusealpha,1);
			OffCommand=cmd(linear,0.2;diffusealpha,0);
		};
	};
	-- bpm display
	Def.ActorFrame{
		InitCommand=cmd(x,SCREEN_CENTER_X-160;y,SCREEN_CENTER_Y-86);
		Def.BPMDisplay {
			File=THEME:GetPathF("_myriadblack","normal");
			Name="BPMDisplay";
			InitCommand=cmd(horizalign,right;shadowlength,0;);
			OnCommand=cmd(stoptweening);
			OffCommand=cmd(linear,0.2;diffusealpha,0);
			SetCommand=function(self) self:SetFromGameState() end;
			CurrentSongChangedMessageCommand=cmd(playcommand,"Set");
			CurrentCourseChangedMessageCommand=cmd(playcommand,"Set");
		};
		LoadFont("_myriadblack","normal")..{
			InitCommand=cmd(horizalign,left;settext,"BPM";shadowlength,0);
			OffCommand=cmd(linear,0.2;diffusealpha,0);
		};
	};
	
	-- sort order display
	LoadFont("_myriadblack","normal")..{
		Name="SortOrderDisplay";
		InitCommand=cmd(x,SCREEN_CENTER_X-148;y,SCREEN_CENTER_Y+24);
		BeginCommand=cmd(horizalign,left;shadowlength,0;zoom,0.6);
		OffCommand=cmd(linear,0.2;diffusealpha,0);
		UpdateCommand=function(self)
			self:settext(SortOrderToLocalizedString(GAMESTATE:GetSortOrder()));
		end;
		SortOrderChangedMessageCommand=cmd(playcommand,'Update');
	};
	
	-- song info
	Def.ActorFrame{
		Name="SongInfoBox";
		InitCommand=cmd(x,SCREEN_CENTER_X-168;y,SCREEN_CENTER_Y+96;draworder,97);
		
		LoadActor("_songinfo box")..{
			InitCommand=cmd(diffusealpha,0);
			OnCommand=cmd(linear,0.2;diffusealpha,1);
			OffCommand=cmd(linear,0.2;diffusealpha,0);
		};
		LoadFont("_myriadblack","gradbev")..{
			Text="Song Information";
			InitCommand=cmd(x,-116;y,-20;horizalign,left;shadowlength,0;zoom,0.5);
			OffCommand=cmd(linear,0.2;diffusealpha,0);
		};
		
		LoadFont("_myriadblack","gradbev") .. {
			Name="SongLength";
			InitCommand=cmd(x,-116;shadowlength,0;diffusealpha,0;zoom,0.8;horizalign,left);
			OnCommand=cmd(linear,0.2;diffusealpha,1);
			OffCommand=cmd(linear,0.2;diffusealpha,0);
			
			SetCommand=function(self)
				local song = GAMESTATE:GetCurrentSong()
				local course = GAMESTATE:GetCurrentCourse()
				if not song and not course then
					self:hidden(1)
					return
				end
				self:hidden(0)
				local time
				if song then time = song:MusicLengthSeconds() end
				if course then
					local st = GAMESTATE:GetCurrentStyle():GetStepsType()
					time = course:GetTotalSeconds( st )
				end
				if time then
					local finalText = SecondsToMSSMsMs(time);
					self:settext( string.sub(finalText, 0, string.len(finalText)-3) );
				else
					self:settext( "xx:xx" );
				end
			end;

			CurrentSongChangedMessageCommand=cmd(playcommand,"Set");
			CurrentCourseChangedMessageCommand=cmd(playcommand,"Set");
		};
		
		LoadFont("_myriadblack","gradbev")..{
			Name="Genre";
			InitCommand=cmd(x,-116;y,16;horizalign,left;shadowlength,0;zoom,0.75;diffusealpha,0);
			OnCommand=cmd(linear,0.2;diffusealpha,1);
			OffCommand=cmd(linear,0.2;diffusealpha,0);
			
			SetCommand=function(self)
				local song = GAMESTATE:GetCurrentSong()
				if not song then self:visible(false); return; end;
				self:visible(true);
				local genre = song:GetGenre();
				self:settext( genre );
			end;
			
			CurrentSongChangedMessageCommand=cmd(playcommand,"Set");
			CurrentCourseChangedMessageCommand=cmd(playcommand,"Set");
		};
	};
	
	-- song options
	LoadFont("Common", "normal") .. {
		InitCommand=cmd(x,SCREEN_CENTER_X-160;y,SCREEN_CENTER_Y+94;playcommand,"Set");
		OnCommand=cmd(zoom,0.5;shadowlength,2;diffusealpha,0;linear,0.5;diffusealpha,1);
		OffCommand=cmd(linear,0.5;diffusealpha,0);

		SetCommand=function(self)
			local sText = GAMESTATE:GetSongOptionsString()
			sText = string.gsub(sText, ", ", "\n")
			self:settext( sText )
			if GAMESTATE:IsAnExtraStage() then
				self:diffuseblink()
			end
		end;
		SongOptionsChangedMessageCommand=cmd(playcommand,"Set");
	};
	
	-- difficulty junk
	Def.ActorFrame{
		Name="DifficultyP1";
		InitCommand=cmd(x,SCREEN_CENTER_X-236;y,SCREEN_CENTER_Y+32;horizalign,left);
		Condition=GAMESTATE:IsHumanPlayer(PLAYER_1);
		
		LoadActor("_difficulty frame")..{
			InitCommand=cmd(diffuse,PlayerColor(PLAYER_1));
		};
		LoadActor("_difficulty mask")..{
			InitCommand=cmd(blend,'BlendMode_NoEffect';zwrite,true;clearzbuffer,true);
		};
		LoadActor("_lines")..{
			InitCommand=cmd(ztest,true;zoomto,138,22;texcoordvelocity,-0.2,0;diffusealpha,0.25);
			CurrentSongChangedMessageCommand=function(self)
				local song = GAMESTATE:GetCurrentSong();
				if not song then self:visible(true); return; end;
				self:visible(false);
			end;
		};
		
		LoadFont("_myriadblack","normal")..{
			InitCommand=cmd(horizalign,left;shadowlength,0;zoom,0.8;x,-64;y,-1);
			OnCommand=cmd();
			SetCommand=function(self)
				local diff = GAMESTATE:GetCurrentSteps(PLAYER_1):GetDifficulty();
				self:settext( DifficultyToLocalizedString(diff) );
				self:diffuse( DifficultyColor(diff) );
			end;
			CurrentStepsP1ChangedMessageCommand=cmd(playcommand,"Set");
			CurrentTrailP1ChangedMessageCommand=cmd(playcommand,"Set");
		};
		DifficultyMeter(PLAYER_1) .. {
			InitCommand=cmd(horizalign,right;x,28;y,-1;diffusealpha,0);
			BeginCommand=cmd(player,PLAYER_1);
			OnCommand=cmd(linear,0.2;diffusealpha,1);
			OffCommand=cmd(linear,0.2;diffusealpha,0);
			CurrentSongChangedMessageCommand=function(self)
				local song = GAMESTATE:GetCurrentSong();
				if not song then self:visible(false); return; end;
				self:visible(true);
			end;
		};
		Autogen(PLAYER_1);
	};
	Def.ActorFrame{
		Name="DifficultyP2";
		InitCommand=cmd(x,SCREEN_CENTER_X-112;y,SCREEN_CENTER_Y+48;horizalign,right);
		Condition=GAMESTATE:IsHumanPlayer(PLAYER_2);
		
		LoadActor("_difficulty frame")..{
			InitCommand=cmd(diffuse,PlayerColor(PLAYER_2));
		};
		LoadActor("_difficulty mask")..{
			InitCommand=cmd(blend,'BlendMode_NoEffect';zwrite,true;clearzbuffer,true);
		};
		LoadActor("_lines")..{
			InitCommand=cmd(ztest,true;zoomto,138,22;texcoordvelocity,-0.2,0;diffusealpha,0.25);
			CurrentSongChangedMessageCommand=function(self)
				local song = GAMESTATE:GetCurrentSong();
				if not song then self:visible(true); return; end;
				self:visible(false);
			end;
		};
		
		LoadFont("_myriadblack","normal")..{
			InitCommand=cmd(horizalign,right;shadowlength,0;zoom,0.8;x,64;y,-1);
			OnCommand=cmd();
			SetCommand=function(self)
				local diff = GAMESTATE:GetCurrentSteps(PLAYER_2):GetDifficulty();
				self:settext( DifficultyToLocalizedString(diff) );
				self:diffuse( DifficultyColor(diff) );
			end;
			CurrentStepsP2ChangedMessageCommand=cmd(playcommand,"Set");
			CurrentTrailP2ChangedMessageCommand=cmd(playcommand,"Set");
		};
		DifficultyMeter(PLAYER_2) .. {
			InitCommand=cmd(horizalign,left;x,-48;y,-1;diffusealpha,0);
			BeginCommand=cmd(player,PLAYER_2);
			OnCommand=cmd(linear,0.2;diffusealpha,1);
			OffCommand=cmd(linear,0.2;diffusealpha,0);
			CurrentSongChangedMessageCommand=function(self)
				local song = GAMESTATE:GetCurrentSong();
				if not song then self:visible(false); return; end;
				self:visible(true);
			end;
		};
		Autogen(PLAYER_2);
	};
	
	--[[
	Def.OptionIconRow {
		Condition=GAMESTATE:IsHumanPlayer(PLAYER_1);
		InitCommand=cmd(x,SCREEN_CENTER_X-300;y,SCREEN_CENTER_Y-182;set,PLAYER_1);
		OnCommand=cmd(zoomy,0;linear,0.5;zoomy,1);
		OffCommand=cmd(linear,0.5;zoomy,0);
		PlayerOptionsChangedP1MessageCommand=cmd(set,PLAYER_1);
	};
	Def.OptionIconRow {
		Condition=GAMESTATE:IsHumanPlayer(PLAYER_2);
		InitCommand=cmd(x,SCREEN_CENTER_X-300;y,SCREEN_CENTER_Y-164;set,PLAYER_2);
		OnCommand=cmd(zoomy,0;linear,0.5;zoomy,1);
		OffCommand=cmd(linear,0.5;zoomy,0);
		PlayerOptionsChangedP2MessageCommand=cmd(set,PLAYER_2);
	};
	]]
	
	-- Do the fade out here, because we want the options message to
	-- appear over it.
	Def.Quad {
		InitCommand=cmd(stretchto,SCREEN_LEFT,SCREEN_TOP,SCREEN_RIGHT,SCREEN_BOTTOM;diffuse,color("#000000"));
		OnCommand=cmd(diffusealpha,0);
		OffCommand=cmd(linear,0.3;diffusealpha,1);
	};
	
	-- it's the NEWWWWWWWWW STYLE! *smoke on the water riff*
	LoadFont("_myriadblack","gradbev")..{
		Text="Press &START; for options";
		InitCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;vertalign,bottom);
		OnCommand=cmd(visible,false);
		ShowPressStartForOptionsCommand=cmd(visible,true;zoom,2;linear,1;zoom,1);
		ShowEnteringOptionsCommand=cmd(finishtweening;accelerate,0.1;zoomy,0);
	};

	-- course shit
	Def.CourseContentsList {
		MaxSongs = 5;

		InitCommand=cmd(x,SCREEN_CENTER_X-160;y,SCREEN_CENTER_Y+96);
		OnCommand=cmd(zoomy,0;bounceend,0.3;zoom,1);
		OffCommand=cmd(zoomy,1;bouncebegin,0.3;zoomy,0);
		ShowCommand=cmd(bouncebegin,0.3;zoomy,1);
		HideCommand=cmd(linear,0.3;zoomy,0);
		SetCommand=function(self)
			self:SetFromGameState();
			self:setsecondsperitem(0.7);
			self:SetSecondsPauseBetweenItems(0.7);
			self:SetLoop(true);
			self:scrollwithpadding(0, 0);
		end;
		CurrentTrailP1ChangedMessageCommand=cmd(playcommand,"Set");
		CurrentTrailP2ChangedMessageCommand=cmd(playcommand,"Set");

		Display = Def.ActorFrame { 
			InitCommand=cmd(setsize,270,44);

			LoadActor("_CourseEntryDisplay bar");

			Def.TextBanner {
				ArtistPrependString="/";
				SetCommand=TextBannerSet;
				InitCommand=cmd(LoadFromString,"", "", "", "", "", "");
				Title = LoadFont("TextBanner","text") .. {
					Name="Title";
					OnCommand=cmd(shadowlength,0);
				};
				Subtitle = LoadFont("TextBanner","text") .. {
					Name="Subtitle";
					OnCommand=cmd(shadowlength,0);
				};
				Artist = LoadFont("TextBanner","text") .. {
					Name="Artist";
					OnCommand=cmd(shadowlength,0);
				};
				SetSongCommand=function(self, params)
					if params.Song then
						self:LoadFromSong( params.Song );
						self:diffuse( SONGMAN:GetSongColor(params.Song) );
					else
						self:LoadFromString( "??????????", "??????????", "", "", "", "" );
						self:diffuse( color("#FFFFFF") );
					end
				end;
			};

			LoadFont("CourseEntryDisplay","number") .. {
				OnCommand=cmd(x,-118;shadowlength,0);
				SetSongCommand=function(self, params) self:settext(string.format("%i", params.Number)); end;
			};

			LoadFont("Common","normal") .. {
				OnCommand=cmd(x,SCREEN_CENTER_X-200;y,-8;zoom,0.7;shadowlength,0);
				DifficultyChangedCommand=function(self, params)
					if params.PlayerNumber ~= GAMESTATE:GetMasterPlayerNumber() then return end
					self:settext( params.Meter );
					self:diffuse( DifficultyColor(params.Difficulty) );
				end;
			};

			LoadFont("Common","normal") .. {
				OnCommand=cmd(x,SCREEN_CENTER_X-192;y,SCREEN_CENTER_Y-230;horizalign,right;zoom,0.5;shadowlength,0);
				SetSongCommand=function(self, params) self:settext(params.Modifiers); end;
			};

			LoadFont("CourseEntryDisplay","difficulty") .. {
				OnCommand=cmd(x,SCREEN_CENTER_X-222;y,-8;shadowlength,0;settext,"1");
				DifficultyChangedCommand=function(self, params)
					if params.PlayerNumber ~= GAMESTATE:GetMasterPlayerNumber() then return end
					self:diffuse( DifficultyColor(params.Difficulty) );
				end;
			};
		};
	};

	LoadFont("_numbers2") .. {
		InitCommand=cmd(x,SCREEN_CENTER_X-262;y,SCREEN_CENTER_Y-126);
		OnCommand=cmd(shadowlength,0;addx,-SCREEN_WIDTH;bounceend,0.5;addx,SCREEN_WIDTH);
		OffCommand=cmd(bouncebegin,0.5;addx,-SCREEN_WIDTH);

		SetCommand=function(self)
			local Course = GAMESTATE:GetCurrentCourse()
			if not Course then
				self:hidden(1)
				return
			end

			self:hidden(0)
			self:settext( Course:GetEstimatedNumStages() );
		end;

		CurrentCourseChangedMessageCommand=cmd(playcommand,"Set");
	};
};
return t;
