

--
-- Widgets are like gui controls in the 3D world(!!!)
--

widgets = {}

--
-- Holds the currently hovered widget
-- 
widgets.Hovered = nil
widgets.HoveredPos = Vector( 0, 0, 0 )

--
-- Holds the current pressed widget
-- 
widgets.Pressed = nil

local function UpdateHovered( pl, mv )

	if ( !IsValid( pl ) ) then return end

	if ( !pl:Alive() ) then 
		pl:SetHoveredWidget( NULL ) 
		return 
	end

	local OldHovered = pl:GetHoveredWidget()
	pl:SetHoveredWidget( NULL )

	local trace = 
	{
		start	= pl:EyePos(),
		endpos	= pl:EyePos() + pl:GetAimVector() * 256,
		filter	= function( ent )
		
					  return ent:IsValid() && ent:IsWidget()
		
				  end
	}
		
--	debugoverlay.Line( trace.start, trace.endpos, 0.5 )

	widgets.Tracing = true
	local tr = util.TraceLine( trace )
	widgets.Tracing = false


	
	if ( !IsValid( tr.Entity ) ) then return end
	if ( tr.Entity:IsWorld() ) then return end
	if ( !tr.Entity:IsWidget() ) then return end

--	debugoverlay.Cross( tr.HitPos, 1, 60 )
	
	if ( OldHovered != tr.Entity ) then
		
		-- On hover changed? why bother?
		
	end
	
	pl:SetHoveredWidget( tr.Entity )
	pl.WidgetHitPos = tr.HitPos

end

local function UpdateButton( pl, mv, btn, mousebutton )

	local now = mv:KeyDown( btn )
	local was = mv:KeyWasDown( btn )
	local hvr = pl:GetHoveredWidget()
	local prs = pl:GetPressedWidget()
	
	if ( now && !was && IsValid( hvr ) ) then
		hvr:OnPress( pl, mousebutton, mv ) 
	end
	
	if ( !now && was && IsValid( prs ) ) then
		prs:OnRelease( pl, mousebutton, mv )	
	end
end


--
-- The idea here is to have exactly the same 
-- behaviour on the client as the server.
--
function widgets.PlayerTick( pl, mv )

	UpdateHovered( pl, mv )
	
	UpdateButton( pl, mv, IN_ATTACK, 1 )
	UpdateButton( pl, mv, IN_ATTACK2, 2 )
	
	local prs = pl:GetPressedWidget()
	
	if ( IsValid( prs ) ) then
		prs:PressedThinkInternal( pl, mv )
	end
	
end


---
---  Render the widgets!
---

local RenderList = {}

function widgets.RenderMe( ent )

	--
	-- The pressed widget gets to decide what should draw
	--
	if ( LocalPlayer() && IsValid(LocalPlayer():GetPressedWidget()) ) then
	
		if ( !LocalPlayer():GetPressedWidget():PressedShouldDraw( ent ) ) then 
			return 
		end
	
	end
	

	table.insert( RenderList, ent )

end

hook.Add( "PostDrawEffects", "RenderWidgets", function() 

	--
	-- Don't do anything if we don't have widgets to render!
	--
	if ( #RenderList == 0 ) then return end

	cam.Start3D( EyePos(), EyeAngles() )

		for k, v in pairs( RenderList ) do
	
			v:OverlayRender()
	
		end
	
	cam.End3D()
	
	RenderList = {}

end )


hook.Add( "PlayerTick", "TickWidgets", function( pl, mv ) widgets.PlayerTick( pl, mv ) end )




local ENTITY = FindMetaTable( "Entity" )

function ENTITY:IsWidget()
	return self.Widget
end