--Midiman (Run 2): Before you do shit:
    --FrameStretchOnCommand:    for frames, stretch the silver frame to its normal size
    --LoadLifeMeterFramePart:   Makes Frame, Loads FrameStretchOnCommand
    --SingleLifeMeter:  Returns style, returns style if mode is 1P
    --VersusMeter:      returns the DP visbar parameters and values ( such as width, sections, etc) 
    
--[[ local FrameStretchOnCommand = function(self, ...)
    --Midiman: Boy, I had to look up recursively just to see what the fuck was happening
--~ 	self:stoptweening();
--~ 	self:playcommand( "SetSize", { Width=200 } );

--~ 	self:RunCommandsRecursively( cmd(sleep,1.5) );
--~ 	self:RunCommandsRecursively( cmd(linear,0.1) );
--~ 	self:playcommand( "SetSize", { Width=SCREEN_WIDTH, tween = cmd(linear,0.1); } );
    --Midiman: we're gonna make a single player lifebar, sorry niggers.
        self:stoptweening();
        self:playcommand( "SetSize", { Width=SCREEN_WIDTH/2, tween = cmd(finishtweening); } );
end

local function LoadLifeMeterFramePart(f)
    --Midiman: Look up above. make a custom frame ( who wants to put lifebar shit in /frame files 3x1? ), and then animate ( above )
	return LoadActor( THEME:GetPathG("_frame", "1D"),
		{ 34/168, 4/168, 92/168, 4/168, 34/168 },
		LoadActor( f )
	) .. {
		InitCommand = cmd(x,SCREEN_CENTER_X;y,SCREEN_TOP+32);
		OnCommand = FrameStretchOnCommand;
	};
end --]]

local function SingleLifeMeter()
    --Midiman: Neccesary?
	local style = GAMESTATE:GetCurrentStyle();
	return style and style:GetStyleType() == "StyleType_OnePlayerTwoSides";
end
	local function Shown()
		if not GAMESTATE:IsHumanPlayer(PLAYER_1) or not GAMESTATE:IsHumanPlayer(PLAYER_2) then
			return false;
		end

		if PlayerStats[1]:GetPossibleDancePoints() ~= PlayerStats[2]:GetPossibleDancePoints() then
			return false;
		end

		if GAMESTATE:IsCourseMode() then
			if GAMESTATE:GetCurrentTrail(PLAYER_1) ~= GAMESTATE:GetCurrentTrail(PLAYER_2) then
				return false;
			end
		else
			if GAMESTATE:GetCurrentSteps(PLAYER_1) ~= GAMESTATE:GetCurrentSteps(PLAYER_1) then
				return false;
			end
		end
		return true;
	end
local TopFrame = Def.ActorFrame {
    --Midiman (Run 2): Needed
};

local function LifeMeterWidth()
    --Midiman (Run 2): SINGLE / DOUBLE.
	return SingleLifeMeter() and ((SCREEN_WIDTH)-32) or ((SCREEN_WIDTH/2)-16)
--~ 	return (SCREEN_WIDTH/2)-16
end

local FrameStretchOnCommand = function(self, ...)
    --Midiman: Boy, I had to look up recursively just to see what the fuck was happening
--~ 	self:stoptweening();
--~ 	self:playcommand( "SetSize", { Width=200 } );

--~ 	self:RunCommandsRecursively( cmd(sleep,1.5) );
--~ 	self:RunCommandsRecursively( cmd(linear,0.1) );
--~ 	self:playcommand( "SetSize", { Width=SCREEN_WIDTH, tween = cmd(linear,0.1); } );
    --Midiman: we're gonna make a single player lifebar, sorry niggers.
        self:stoptweening();
        self:playcommand( "SetSize", { Width=LifeMeterWidth(), tween = cmd(finishtweening); } );
end

local function LoadLifeMeterFramePart(f)
    --Midiman: Look up above. make a custom frame ( who wants to put lifebar shit in /frame files 3x1? ), and then animate ( above )
	return LoadActor( THEME:GetPathG("_frame", "1D"),
		{ 34/168, 4/168, 92/168, 4/168, 34/168 },
		LoadActor( f )
	) .. {
		InitCommand = cmd(x,SCREEN_CENTER_X;y,SCREEN_TOP+32);
		OnCommand = FrameStretchOnCommand;
	};
end

local X = {
    --Midiman: for Lifebars themselves, not for actorframes. for this project, we're making a solo lifebar
--[[ 	[PLAYER_1] = SCREEN_CENTER_X/2+8, --Midiman: I forget that to use horizalign,center, you've got to half what your center destination is. woo
	[PLAYER_2] = SCREEN_RIGHT-16, --]]
    [PLAYER_1] = SCREEN_LEFT + 16,
    [PLAYER_2] = SCREEN_RIGHT - 16
};

for pn in ivalues(PlayerNumber) do
    --Midiman: get those lifebars again, get X for PLAYER*, load meter stuff
	TopFrame[#TopFrame+1] = Def.ActorFrame {
		InitCommand=cmd(x,X[pn]);
		LoadActor("meter under") .. {
			Name = "Under"; 
			InitCommand=cmd(
				y,SCREEN_TOP+30;
				zoomx,pn == PLAYER_1 and 1 or -1
			);
			BeginCommand=cmd(
				zoomtowidth,LifeMeterWidth();
				x,LifeMeterWidth()/2 * (pn == PLAYER_1 and 1 or -1);
				visible,GAMESTATE:IsHumanPlayer(pn)
				);
            --Midiman (Run 2): remove animations
            --Midinan (Run 2) Edit: Ok, 'visible,true' absolutely ruins meter under. oh well
			OnCommand=cmd(diffusealpha,1;);
			OffCommand=cmd(zoomx,1;linear,0.3;zoomx,0);
		};
	};
end
    --Midiman: Quantize and limit the rounding interval of the value and whatever
	local function Quantize( f, fRoundInterval ) return math.floor( (f + fRoundInterval/2)/fRoundInterval ) * fRoundInterval end

for pn in ivalues(PlayerNumber) do
    --Midiman: HUGE FUCKING THING THAT DEFINES THE BAOVE ROOOOAHGLAHGLAHGLHALGHLHLHLEE3333
	local c;
	local meter;
	local fMeterWidth;
	local fMeterRatio;
    --Midiman: remember when I said you had to update shit? well now you get why :(. now if only StepMania had an ALWAYS function like MMF does
	local function Update(self)
		if not meter then
			return;
		end

		local life = meter:GetLife();
        --Midiman: once we hit 0 on our timer, get the aux of TweenHelper, which is usually our life
		if c.TweenHelper:GetTweenTimeLeft() ~= 0 then
			life = c.TweenHelper:getaux();
		end;
        --Midiman: SongBeatVisible() works here I guess. good
		local fBeat = GAMESTATE:GetSongBeatVisible();
        --Midiman: get remainder of beat excess? I dont know, I never did learn divison
		local fBeatFract = fBeat % 1;

		if c.Grad:GetTweenTimeLeft() == 0 then
			-- Each section in the texture is 8 texels wide, including 2 pixels
			-- of separator on the right edge.  The whole life meter is ideally
			-- LifeMeterWidth wide, and exactly fMeterWidth wide (fMeterWidth*fMeterRatio
			-- pixels).  full width (no crop) = fMeterWidth; 
			local fSectionWidth = 8*fMeterRatio;
			local fSeparatorWidth = 2*fMeterRatio;
			local fPulseSections = 4;

			local fPos = life * fMeterWidth;
			fPos = Quantize(fPos, fSectionWidth);
			fPos = fPos - fSeparatorWidth;
			local fPulseDistance = (fPulseSections * fSectionWidth);
			fPulseDistance = fPulseDistance / fMeterWidth;
			fPos = fPos / fMeterWidth;

			local fTipPos = math.min(life, 1.0) * fMeterWidth;
			fTipPos = Quantize(fTipPos, fSectionWidth);
			fTipPos = fTipPos - fSeparatorWidth/2;
			fTipPos = fTipPos;

			local fPulse = scale( fBeatFract, 0.0, 0.25, 0, fPulseDistance );
			fPulse = clamp( fPulse, 0, fPulseDistance );
			if c.TweenHelper:GetTweenTimeLeft() ~= 0 then
				fPulse = fPulseDistance;
			end;
			fPos = fPos - fPulse;

			c.Grad:cropright( 1-fPos );

			local fFlip = (pn == PLAYER_1 and 1 or -1 );
			c.Tip:x( X[pn] + (fTipPos * fFlip) );
			c.Tip:visible( fTipPos >= 0.01 );
			local fVisible = scale( life, 0.95, 1.00, 1, 0 );
			c.Tip:basealpha(fVisible);
		end
        --Midiman: From what I said before: ditch our rules, and fucking grab the new life. aux is 0.5 because that is the common lifebar startup value for dance game
		-- This doesn't follow aux.
		local life = meter:GetLife();
		local fVisible = scale( life, 0.80, 1.00, 0, 1 );
		c.Filled:diffusealpha(fVisible);
        --Midiman: prepare the next additions for this actorframe to support the values we give it ( namely, loading actors with their names intact )
		local fDist;
		fDist = scale( fBeatFract, 0.0, 1.00, 0, 0.25 );
		fDist = clamp( fDist, 0, 0.25 );
		c.Filled:SetCustomImageRect( 0.25 - fDist, 0, 0.75 + fDist, 1 );
	end

	TopFrame[#TopFrame+1] = Def.ActorFrame {
		LoadActor("meter grad") .. { Name = "Grad"; };
		LoadActor("meter danger") .. { Name = "Danger"; };
		LoadActor("meter tip") .. { Name = "Tip"; };
		LoadActor("meter filled") .. { Name = "Filled"; };
		LoadActor("meter tick") .. { Name = "Tick"; };
		Def.Actor {
			Name = "TweenHelper";
		};
        LoadLifeMeterFramePart("top frame 1") .. { OnCommand = cmd(horizalign,(pn == PLAYER_1) and left or right;x,X[pn];addx,(pn == PLAYER_1) and -8 or 8;player,PLAYER_1); };

		-- sort of ugly
		--[[	LoadFont("_venacti shadow 15px normal") .. {
				Name = "PlayerName";
				InitCommand=cmd(x,X[pn]);
				BeginCommand=function(self)
					self:player(pn);
					local profile = PROFILEMAN:GetProfile( pn );
					local name = profile:GetDisplayName();
					self:settext( name );
					self:shadowlength(0);
				end;

				OnCommand=cmd(x,140 * (pn == PLAYER_1 and 1 or -1);y,32);
			};
		]]
		--OnCommand=cmd(zoomx,0;sleep,2.2;linear,0.3;zoomx,1);
		--OffCommand=cmd(zoomx,1;linear,0.3;zoomx,0);
		
		InitCommand = function(self)
			self:SetUpdateFunction( Update );
            --Midman: I guess this is an actual function for ActorFrames. update our children
			c = self:GetChildren();
			local f = cmd(
                --Midiman: width /2 ensures we have enough for doubles and singles. 
				x,X[pn]+LifeMeterWidth()/2 * (pn == PLAYER_1 and 1 or -1);
				y,SCREEN_TOP+30;
				zoomx,pn == PLAYER_1 and 1 or -1
			);
			f(c.Grad);
			f(c.Danger);
			f(c.Tick);
			f(c.Filled);
		--	f(c.PlayerName);
		end;

		BeginCommand=function(self)
			self:player(pn);
			if not GAMESTATE:IsHumanPlayer(pn) then
				return;
			end
            --Midiman: setup meter again. I guess they do alot of home checking before they take themselves out to play
			meter = SCREENMAN:GetTopScreen():GetLifeMeter(pn);

			c.Tick:player(pn);
			c.Tick:halign(0);
			c.Tick:SetTextureFiltering(false);
			c.Tick:x( X[pn] );
			c.Tick:y( SCREEN_TOP+30 );
			c.Tick:diffusealpha(0.4);
			local fFlip = (pn == PLAYER_1 and 1 or -1 );

			local fDisplayWidth = DISPLAY:GetDisplayWidth();
			local fScreenWidth = SCREEN_WIDTH;
			local fRatio = fScreenWidth/fDisplayWidth;
			-- 1/4 -> *4 is fine (== 1)
			-- 1/3 -> *3
			-- 2/3 -> *2 -> 4/3
			local fAdjusted = math.floor( 1/fRatio + 0.5 );
			if fAdjusted > 0.001 then
				fRatio = fRatio*fAdjusted;
			end;
			c.Tick:zoomx(fRatio * fFlip);

			local fTicksWidth = LifeMeterWidth();
			fTicksWidth = fTicksWidth/fRatio;
			fTicksWidth = math.ceil(fTicksWidth / 8) * 8;
			c.Tick:SetCustomImageRect( 0, 0, fTicksWidth/8, 1 );
			c.Tick:SetWidth( fTicksWidth );
			fMeterWidth = fTicksWidth*fRatio;
			fMeterRatio = fRatio;
            --Midiman: flashy shit for lifebar
			c.Grad:halign(0);
			c.Grad:x( X[pn] );
			c.Grad:SetWidth( fMeterWidth );
			c.Grad:zoomx(fFlip);
			c.Grad:diffusealpha(1);
			c.Danger:halign(0);
			c.Danger:x( X[pn] );
			c.Danger:SetWidth( fMeterWidth );
			c.Danger:zoomx(fFlip);
			c.Danger:diffuseshift();
			c.Danger:effectcolor1(color("#FFFFFF40"));
			c.Danger:effectcolor2(color("#FFFFFFC0"));
			c.Danger:diffusealpha(0);
			c.Filled:halign(0);
			c.Filled:x( X[pn] );
			c.Filled:SetWidth( fMeterWidth );
			c.Filled:zoomx(fFlip);
			c.Filled:glowshift();
			c.Filled:effectclock("beat");
			c.Filled:effectperiod(1.000);
			c.Filled:effectcolor1(color("#FFFFFF00"));
			c.Filled:effectcolor2(color("#FFFFFF40"));

			c.Tip:zoomx(fRatio);
			c.Tip:y( SCREEN_TOP+30 );

			c.Tick:x( math.floor( c.Tick:GetX()/fRatio )*fRatio );
		end;
		HealthStateChangedMessageCommand = function(self, params)
			if params.PlayerNumber ~= pn then return; end
			local bDanger = params.HealthState == "HealthState_Danger" or
				params.HealthState == "HealthState_Dead";
			c.Danger:stoptweening();
			c.Danger:linear(0.3);
			c.Danger:diffusealpha(bDanger and 1 or 0);
		end;

		OnCommand=function(self)
			(cmd(finishtweening;diffusealpha,1;fadeleft,0.25;cropleft,1;sleep,2.0;linear,0.3;cropleft,-0.25;
			     linear,0.2;diffusealpha,0.4))(c.Tick);

			c.TweenHelper:aux(0.0);
			c.TweenHelper:sleep(2.0);
			c.TweenHelper:decelerate(0.3);
			c.TweenHelper:aux(0.5);
		end;

		PlayerFailedMessageCommand=function(self, params)
			if params.PlayerNumber ~= pn then return; end

			c.TweenHelper:aux(0.0);
			c.TweenHelper:decelerate(0.3);
			c.TweenHelper:aux(1.0);
			c.Grad:diffusealpha(0);
			c.Danger:effectcolor1(color("#FFFFFFC0"));
			c.Danger:effectcolor2(color("#FFFFFFC0"));
			(cmd(finishtweening;fadeleft,0;cropleft,0;decelerate,0.3;cropleft,1))(c.Tick);
		end;
	};
end
--[[ --Midiman: TOP FRAME ( VERSUS )
TopFrame[#TopFrame+1] = LoadLifeMeterFramePart("top frame 1") .. { OnCommand = cmd(x,SCREEN_CENTER_X); };
--Midiman: TOP FRAME ( DOUBLE )
TopFrame[#TopFrame+1] = LoadLifeMeterFramePart("top frame 2") .. { OnCommand = cmd(visible,false); }; --]]

local Overlay = Def.ActorFrame {
	TopFrame,
};

return Overlay;
