-- Common things you'll find on every Eval screen.
-- With luck, they should position themselves.

-- xxx: modularize the hell out of these.

-- tap note types
-- (iterating through the enum isn't a good idea as everything's backwards)
local TNSNames = {
	THEME:GetString("TapNoteScore","W1"),
	THEME:GetString("TapNoteScore","W2"),
	THEME:GetString("TapNoteScore","W3"),
	THEME:GetString("TapNoteScore","W4"),
	THEME:GetString("TapNoteScore","W5"),
	THEME:GetString("TapNoteScore","Miss"),
	THEME:GetString("ScreenEvaluation","Holds"),
	THEME:GetString("ScreenEvaluation","Max Combo")
};

-- JudgeLabels()
-- Print all the boring labels.
local function JudgeLabels()
	local l = Def.ActorFrame{};

	for i=1,#TNSNames do
		l[#l+1] = AutoText("frutiger")..{
			InitCommand=cmd(shadowlength,1;NoStroke;zoom,0.833);
			BeginCommand=function(self)
				self:y((i-1)*24);
				self:settext(TNSNames[i]);
				if i < 6 then -- W1-W5
					self:diffuse( JudgeColor('TapNoteScore_W'..i) );
				elseif i == 6 then -- Miss
					self:diffuse( JudgeColor('TapNoteScore_Miss') );
				elseif i == 7 then -- holds
					self:diffuse( JudgeColor('TapNoteScore_W1') );
				elseif i == 8 then -- max combo
					self:diffuse( PlayerColor(PLAYER_1) );
				end;
			end;
		};
	end;

	return l;
end;

local TNSTypes = {
	'TapNoteScore_W1',
	'TapNoteScore_W2',
	'TapNoteScore_W3',
	'TapNoteScore_W4',
	'TapNoteScore_W5',
	'TapNoteScore_Miss'
};

-- MaxCombo(pn)
-- Gets pn's max combo. Used by JudgeNumbers.
local function MaxCombo(pn)
	local stats = STATSMAN:GetCurStageStats():GetPlayerStageStats(pn);

	return AutoText("frutiger")..{
		Text=stats:MaxCombo();
		InitCommand=cmd(shadowlength,1;NoStroke;zoom,0.833);
		BeginCommand=function(self)
			self:horizalign( (pn == PLAYER_1) and right or left );
			self:visible( GAMESTATE:IsPlayerEnabled(pn) );

			self:diffuse(PlayerColor(pn));
			self:textglowmode('TextGlowMode_Inner');

			local bFailed = stats:GetFailed()
			-- todo: check for little, other chart-modifying modifiers.
			local bHasFullCombo = false;
			local tnsComboThreshold = THEME:GetMetric("Gameplay","MinScoreToContinueCombo");
			bHasFullCombo = stats:FullComboOfScore(tnsComboThreshold)

			-- don't do this if using little.
			if GAMESTATE:PlayerIsUsingModifier(pn,"little") then
				self:stopeffect()
			else
				if bHasFullCombo and not bFailed then
					self:glowshift();
					self:effectcolor1(PlayerColor(pn));
					self:effectcolor2(color("1,1,1,1"));
				else
					self:stopeffect();
				end;
			end
		end;
	};
end;

-- JudgeNumbers(pn)
-- Print all the numbers.
local function JudgeNumbers(pn)
	local n = Def.ActorFrame{};
	local stats = STATSMAN:GetCurStageStats():GetPlayerStageStats(pn);

	-- do the normals first
	for i=1,#TNSTypes do
		n[#n+1] = AutoText("frutiger")..{
			InitCommand=cmd(shadowlength,1;NoStroke;zoom,0.833);
			BeginCommand=function(self)
				self:y((i-1)*24);
				self:settext(stats:GetTapNoteScores(TNSTypes[i]));
				self:diffuse(PlayerColor(pn));
				self:halign( (pn == PLAYER_1) and 1 or 0 );
				self:visible( GAMESTATE:IsPlayerEnabled(pn) );
			end;
		};
	end;
	-- then add the flashing marvelous count
	n[#n+1] = AutoText("frutiger")..{
		InitCommand=cmd(shadowlength,1;NoStroke;zoom,0.65);
		BeginCommand=function(self)
			local xMult = pn == PLAYER_1 and -1 or 1;
			self:x( 78 * xMult );
			self:diffuse(PlayerColor(pn));
			self:horizalign( pn == PLAYER_1 and right or left );

			-- visibility, setting correct text and such
			local flashingMarvs = tonumber( getenv( "FlashingMarvs"..pname(pn) ) );
			if flashingMarvs then
				if not GAMESTATE:IsPlayerEnabled(pn) or flashingMarvs < 1 then
					self:visible(false);
				else
					self:visible(true);
					self:settext( flashingMarvs );
					self:glowshift();
					self:effectcolor1( color("1,1,1,0") );
					self:effectcolor2( color("1,1,1,0.75") );
					self:effectperiod( 0.25 );
				end;
			else
				self:visible(false);
			end
		end;
	};
	-- now for the holds and drops
	local OK = stats:GetHoldNoteScores('HoldNoteScore_Held');
	local NG = stats:GetHoldNoteScores('HoldNoteScore_LetGo');
	local lenOK = string.len(OK);
	local lenNG = string.len(NG);
	local attribOK = { Length = lenOK; Diffuse = PlayerColor(pn); };
	local attribSlash = { Length = 1; Diffuse = color("1,1,1,1"); };
	local attribNG = { Length = lenNG; Diffuse = JudgeColor('TapNoteScore_Miss'); };

	n[#n+1] = AutoText("frutiger")..{
		Text=OK.."/"..NG;
		InitCommand=cmd(shadowlength,1;NoStroke;zoom,0.833);
		BeginCommand=function(self)
			self:y(24*(#TNSNames-2));
			self:AddAttribute(0,attribOK);
			self:AddAttribute(lenOK,attribSlash);
			self:AddAttribute(lenOK+1,attribNG);
			self:horizalign( (pn == PLAYER_1) and right or left );
			self:visible( GAMESTATE:IsPlayerEnabled(pn) );
		end;
	};

	n[#n+1] = MaxCombo(pn)..{ InitCommand=cmd(y,24*(#TNSNames-1)); };

	return n;
end;

-- Percentage(pn)
-- Gets the percentage for the specified player.
-- [dubaiOne v1.3] percent now glows on all perfects or better.
local function Percentage(pn)
	local stats = STATSMAN:GetCurStageStats():GetPlayerStageStats(pn);
	local percent = stats:GetPercentDancePoints();

	local grade = stats:GetGrade();

	return AutoText("frutiger")..{
		Name="Score"..pn;
		Text=FormatPercentScore(percent);
		InitCommand=cmd(NoStroke;shadowlength,1);
		BeginCommand=function(self)
			local text = self:GetText();
			-- orangenoise shortcut
			if text == "100.00%" then self:SetText("100%");
			end;

			local diff;

			if GAMESTATE:IsCourseMode() then
				diff = GAMESTATE:GetCurrentTrail(pn):GetDifficulty();
			else
				diff = GAMESTATE:GetCurrentSteps(pn):GetDifficulty();
			end;
			self:diffuse( DifficultyColor(diff) );
			self:textglowmode('TextGlowMode_Inner');

			if grade == 'Grade_Tier01' or grade == 'Grade_Tier02' then
				self:glowshift();
			else
				self:stopeffect();
			end;

			self:visible( GAMESTATE:IsPlayerEnabled(pn) );
		end;
	};
end;

-- RecordTexts(pn)
-- Gets record texts for specified player.
local function RecordTexts(pn)
	local r = Def.ActorFrame{};
	local stats = STATSMAN:GetCurStageStats():GetPlayerStageStats(pn);

	-- note: only shows top score
	local highScoreIndex = {
		Machine = stats:GetMachineHighScoreIndex(),
		Personal = stats:GetPersonalHighScoreIndex(),
	}

	local bMachineRecord  = (  highScoreIndex.Machine ~= -1 ) and stats:GetPercentDancePoints() >= 0.01;
	local bPersonalRecord = ( highScoreIndex.Personal ~= -1 ) and stats:GetPercentDancePoints() >= 0.01;

	r[#r+1] = AutoText("frutiger")..{
		Text=string.format("Machine Record #%i!", highScoreIndex.Machine+1);
		InitCommand=cmd(zoom,0.55;shadowlength,1;shadowcolor,PlayerDarkColor(pn);diffuse,PlayerColor(pn);NoStroke;glowshift;effectcolor1,color("1,1,1,0");effectcolor2,color("1,1,1,0.25"));
		BeginCommand=cmd(visible,bMachineRecord;);
	};

	r[#r+1] = AutoText("frutiger")..{
		Text=string.format("Personal Record #%i!", highScoreIndex.Personal+1);
		InitCommand=cmd(y,16;zoom,0.55;shadowlength,1;shadowcolor,PlayerDarkColor(pn);diffuse,PlayerColor(pn);NoStroke;glowshift;effectcolor1,color("1,1,1,0");effectcolor2,color("1,1,1,0.25"));
		BeginCommand=cmd(visible,bPersonalRecord;);
	};

	return r;
end;

-- Awards(pn)
-- Get awards for specified player.

-- low priority; make it happen if time permits.
local function Awards(pn)
	local stats = STATSMAN:GetCurStageStats():GetPlayerStageStats(pn);
	local a = Def.ActorFrame{};

	-- GetPerDifficultyAward

	return a;
end;

-- StagesSurvived(pn)
-- Gets the stages survived for the current player.
local function StagesSurvived(pn)
	return AutoText("frutiger")..{
		InitCommand=cmd(shadowlength,1;Stroke,color("0.2,0.2,0.2,0.35");zoom,0.8);
		BeginCommand=function(self)
			if not GAMESTATE:IsCourseMode() then return; end;

			-- visibility
			if not GAMESTATE:IsPlayerEnabled(pn) then
				self:visible(false);
			end;
			--self:horizalign( (pn == PLAYER_1) and right or left );

			local text = "";
			local proxy = SCREENMAN:GetTopScreen():GetChild( 'SurvivedNumber'..pname(pn) );
			if proxy then
				text = proxy:GetText();
			end;
			local stageText = "stage"
			if text ~= "01" then
				stageText = stageText .."s"
			end
			self:settext( text .." ".. stageText );
		end;
	};
end;

local function StepsType(pn)
	if not GAMESTATE:IsPlayerEnabled(pn) then
		return Def.Actor{};
	end;

	local StepsOrTrail;
	if GAMESTATE:IsCourseMode() then
		StepsOrTrail = GAMESTATE:GetCurrentTrail(pn);
	else
		StepsOrTrail = GAMESTATE:GetCurrentSteps(pn);
	end;

	local StepsType = StepsOrTrail:GetStepsType();
	local stringloc = string.sub(StepsType,11);

	local ret = Def.ActorFrame{};
	if StepsOrTrail then
		ret[#ret+1] = AutoText("frutiger")..{
			Text=THEME:GetString("StepsType",stringloc);
			InitCommand=cmd(Stroke,color("0.2,0.2,0.2,0.35");shadowlength,1;zoom,0.666);
		};
	end;

	return ret;
end;

local common = Def.ActorFrame{
	-- background
	LoadActor( THEME:GetPathB("","_frame 3x3"), "_eval", 244,282 )..{
		InitCommand=cmd(CenterX;y,SCREEN_CENTER_Y+55);
	};
	-- separator
	Def.Quad{
		InitCommand=cmd(CenterX;y,SCREEN_CENTER_Y-40;zoomto,250,4;diffuse,color("#000000");fadeleft,0.25;faderight,0.25);
	};
	-- labels
	JudgeLabels()..{ InitCommand=cmd(CenterX;y,SCREEN_CENTER_Y-24); };

	-- song/course title bg
	Def.Quad{
		InitCommand=cmd(CenterX;y,SCREEN_TOP+27;zoomto,SCREEN_WIDTH,36;diffuse,color("0,0,0,0.75");fadeleft,0.5;faderight,0.5);
	};
	-- song/course title text
	AutoText("frutiger",true)..{
		InitCommand=cmd(CenterX;y,SCREEN_TOP+26;NoStroke;shadowlength,1;zoom,0.55);
		BeginCommand=function(self)
			local song = GAMESTATE:GetCurrentSong();
			local course = GAMESTATE:GetCurrentCourse();
			local s = "";
			if GAMESTATE:IsCourseMode() then
				s = course:GetDisplayFullTitle();
			else
				s = song:GetDisplayFullTitle() .. "\n" .. song:GetDisplayArtist();
			end;

			-- apply title fun, but only if we have a song.
			if song then
				-- DVNO is four capital letters printed in gold.
				if song:GetDisplayFullTitle() == "DVNO" then
					local attribDVNO = {
						Length = 4;
						Diffuse = color("1,0.8,0,1");
					};
					self:AddAttribute(0,attribDVNO);
				end;
			end;

			self:settext(s);
		end;
	};
	-- song options
	AutoText("frutiger")..{
		Text=GAMESTATE:GetSongOptionsString();
		InitCommand=cmd(CenterX;y,SCREEN_CENTER_Y-90;NoStroke;zoom,0.6;shadowlength,1);
	};

	-- Player 1!
	Def.ActorFrame{
		Name="P1Results";
		BeginCommand=function(self)
			self:visible(GAMESTATE:IsSideJoined(PLAYER_1))
		end;

		-- percentage
		Percentage(PLAYER_1)..{
			InitCommand=cmd(x,SCREEN_CENTER_X-80;y,SCREEN_CENTER_Y-80);
		};

		-- steps type
		StepsType(PLAYER_1)..{
			InitCommand=cmd(x,SCREEN_CENTER_X-108;y,SCREEN_CENTER_Y-56);
		};

		-- stages survived (course mode)
		StagesSurvived(PLAYER_1)..{
			InitCommand=cmd(x,SCREEN_WIDTH*0.2;y,SCREEN_CENTER_Y-136);
		};

		-- numb3rs, the hit show on CBS
		JudgeNumbers(PLAYER_1)..{
			InitCommand=cmd(x,SCREEN_CENTER_X-64;y,SCREEN_CENTER_Y-24);
		};

		-- Record Texts
		RecordTexts(PLAYER_1)..{
			InitCommand=cmd(x,SCREEN_CENTER_X-64;y,SCREEN_CENTER_Y+168);
		};

		-- Option Icons
		LoadActor("OptionIcons",PLAYER_1)..{
			InitCommand=cmd(x,SCREEN_CENTER_X*0.25;y,SCREEN_HEIGHT*0.3);
		};
	};

	-- Player 2!
	Def.ActorFrame{
		Name="P2Results";
		BeginCommand=function(self)
			self:visible(GAMESTATE:IsSideJoined(PLAYER_2))
		end;

		-- percentage
		Percentage(PLAYER_2)..{
			InitCommand=cmd(x,SCREEN_CENTER_X+80;y,SCREEN_CENTER_Y-80);
		};

		-- steps type
		StepsType(PLAYER_2)..{
			InitCommand=cmd(x,SCREEN_CENTER_X+108;y,SCREEN_CENTER_Y-56);
		};

		-- stages survived (course mode)
		StagesSurvived(PLAYER_2)..{
			InitCommand=cmd(x,SCREEN_WIDTH*0.8;y,SCREEN_CENTER_Y-136);
		};

		-- numbers
		JudgeNumbers(PLAYER_2)..{
			InitCommand=cmd(x,SCREEN_CENTER_X+64;y,SCREEN_CENTER_Y-24);
		};

		-- Record Texts
		RecordTexts(PLAYER_2)..{
			InitCommand=cmd(x,SCREEN_CENTER_X+64;y,SCREEN_CENTER_Y+168);
		};

		-- Option Icons
		LoadActor("OptionIcons",PLAYER_2)..{
			InitCommand=cmd(x,SCREEN_CENTER_X*1.75;y,SCREEN_HEIGHT*0.3);
		};
	};
};

return common;