--[[
	 _
	( )
   _| |   __   _ __   ___ ___     _ _
 /'_` | /'__`\( '__)/' _ ` _ `\ /'_` )
( (_| |(  ___/| |   | ( ) ( ) |( (_| |
`\__,_)`\____)(_)   (_) (_) (_)`\__,_)

	DColorMixer
--]]


local PANEL = {}


AccessorFunc( PANEL, "m_ConVarR", "ConVarR" )
AccessorFunc( PANEL, "m_ConVarG", "ConVarG" )
AccessorFunc( PANEL, "m_ConVarB", "ConVarB" )
AccessorFunc( PANEL, "m_ConVarA", "ConVarA" )

AccessorFunc( PANEL, "m_bPalette", "Palette", FORCE_BOOL )
AccessorFunc( PANEL, "m_bAlpha", "AlphaBar", FORCE_BOOL )
AccessorFunc( PANEL, "m_bWangsPanel", "Wangs", FORCE_BOOL )

AccessorFunc( PANEL, "m_Color", "Color" )

local BarWide = 26

local function CreateWangFunction( self, colindex )
	local function OnValueChanged( ptxt, strvar )
		if ( ptxt.notuserchange ) then return end

		self.m_Color[colindex] = tonumber( strvar ) or 0
		if ( colindex == "a" ) then
			self.Alpha:SetBarColor( ColorAlpha( self.m_Color, 255 ) )
			self.Alpha:SetValue( self.m_Color.a / 255 )
		else
			self.HSV:SetColor( self.m_Color )

			local h, s, v = ColorToHSV( self.HSV:GetBaseRGB() )
			self.RGB.LastY = ( 1 - h / 360 ) * self.RGB:GetTall()
		end

		self:UpdateColor( self.m_Color )
	end 

	return OnValueChanged
end

--[[---------------------------------------------------------
	Name: Init
-----------------------------------------------------------]]
function PANEL:Init()

	-- The defaults
	self.m_bPalette = true
	self.m_bAlpha = true
	self.m_bWangsPanel = true
	self.m_Color = Color( 255, 0, 0, 255 )

	self.Palette = vgui.Create( "DColorPalette", self )
	self.Palette:Dock( BOTTOM )
	self.Palette:SetVisible( self.m_bPalette )
	self.Palette:SetTall( 75 )
	self.Palette:SetButtonSize( 16 )
	self.Palette:DockMargin( 0, 8, 0, 0 )
	self.Palette:Reset()
	self.Palette.DoClick = function( ctrl, color, btn )
		self:SetColor( Color( color.r, color.g, color.b, self.m_bAlpha and color.a or 255 ) )
	end
	self.Palette.OnRightClickButton = function( ctrl, btn )
		ctrl:SaveColor( btn, self:GetColor() );
	end
	

	-- The label
	self.label = vgui.Create( "DLabel", self )
	self.label:SetText( "" )
	self.label:Dock( TOP )
	self.label:SetDark( true )
	self.label:SetVisible( false )

	--The number stuff
	self.WangsPanel = vgui.Create( "Panel", self )
	self.WangsPanel:SetWide( 50 )
	self.WangsPanel:Dock( RIGHT )
	self.WangsPanel:DockMargin( 4, 0, 0, 0 )
	self.WangsPanel:SetVisible( self.m_bWangsPanel )

	self.txtR = self.WangsPanel:Add( "DNumberWang" )
		self.txtR:SetDecimals( 0 )
		self.txtR:SetMinMax( 0, 255 )
		self.txtR:SetTall( 20 )
		self.txtR:Dock( TOP )
		self.txtR:DockMargin( 0, 0, 0, 0 )
		self.txtR:SetTextColor( Color( 150, 0, 0, 255 ) )

	self.txtG = self.WangsPanel:Add( "DNumberWang" )
		self.txtG:SetDecimals( 0 )
		self.txtG:SetMinMax( 0, 255 )
		self.txtG:SetTall( 20 )
		self.txtG:Dock( TOP )
		self.txtG:DockMargin( 0, 4, 0, 0 )
		self.txtG:SetTextColor( Color( 0, 150, 0, 255 ) )

	self.txtB = self.WangsPanel:Add( "DNumberWang" )
		self.txtB:SetDecimals( 0 )
		self.txtB:SetMinMax( 0, 255 )
		self.txtB:SetTall( 20 )
		self.txtB:Dock( TOP )
		self.txtB:DockMargin( 0, 4, 0, 0 )
		self.txtB:SetTextColor( Color( 0, 0, 150, 255 ) )

	self.txtA = self.WangsPanel:Add( "DNumberWang" )
		self.txtA:SetDecimals( 0 )
		self.txtA:SetMinMax( 0, 255 )
		self.txtA:SetTall( 20 )
		self.txtA:Dock( TOP )
		self.txtA:DockMargin( 0, 4, 0, 0 )
		self.txtA:SetTextColor( Color( 80, 80, 80, 255 ) )

	self.txtR.OnValueChanged = CreateWangFunction( self, "r" )
	self.txtG.OnValueChanged = CreateWangFunction( self, "g" )
	self.txtB.OnValueChanged = CreateWangFunction( self, "b" )
	self.txtA.OnValueChanged = CreateWangFunction( self, "a" )

	-- The colouring stuff
	self.HSV = vgui.Create( "DColorCube", self )
	self.HSV:Dock( FILL )
	self.HSV.OnUserChanged = function( ctrl, color )
		color.a = self.m_Color.a
		self:UpdateColor( color )
	end

	self.RGB = vgui.Create( "DRGBPicker", self )
	self.RGB:Dock( RIGHT )
	self.RGB:SetWidth( BarWide )
	self.RGB:DockMargin( 4, 0, 0, 0 )
	self.RGB.OnChange = function( ctrl, color )
		self:SetBaseColor( color )
	end


	self.Alpha = vgui.Create( "DAlphaBar", self )
	self.Alpha:DockMargin( 4, 0, 0, 0 )
	self.Alpha:Dock( RIGHT )
	self.Alpha:SetVisible( self.m_bAlpha )
	self.Alpha:SetWidth( BarWide )
	self.Alpha.OnChange = function( ctrl, fAlpha )
		self.m_Color.a = math.floor( fAlpha * 255 )
		self:UpdateColor( self.m_Color )
	end




	-- Layout
	self:UpdateColor( self.m_Color )
	self:SetSize( 256, 230 )
	self:InvalidateLayout()

end

--[[---------------------------------------------------------
	Name: SetLabel
-----------------------------------------------------------]]
function PANEL:SetLabel( text )

	if ( !text or ( text == "" ) ) then
		self.label:SetVisible( false )
	
		return
	end

	self.label:SetText( text )
	self.label:SetVisible( true )

	self:InvalidateLayout()
end


--[[---------------------------------------------------------
	Name: SetPalette
-----------------------------------------------------------]]
function PANEL:SetPalette( bEnabled )
	self.m_bPalette = bEnabled

	local Palette = self.Palette
	Palette:SetVisible( bEnabled )

	self:InvalidateLayout()
end

--[[---------------------------------------------------------
	Name: SetAlphaBar
-----------------------------------------------------------]]
function PANEL:SetAlphaBar( bEnabled )
	self.m_bAlpha = bEnabled

	local Alpha = self.Alpha
	Alpha:SetVisible( bEnabled )

	local AlphaWang = self.txtA
	AlphaWang:SetVisible( bEnabled )

	self:InvalidateLayout()
end

--[[---------------------------------------------------------
	Name: SetWangs
-----------------------------------------------------------]]
function PANEL:SetWangs( bEnabled )
	self.m_bWangsPanel = bEnabled

	local WangsPanel = self.WangsPanel
	WangsPanel:SetVisible( bEnabled )

	self:InvalidateLayout()
end

--[[---------------------------------------------------------
	Name: ConVarR
-----------------------------------------------------------]]
function PANEL:SetConVarR( cvar )
	self.m_ConVarR = cvar
end

--[[---------------------------------------------------------
	Name: ConVarG
-----------------------------------------------------------]]
function PANEL:SetConVarG( cvar )
	self.m_ConVarG = cvar
end

--[[---------------------------------------------------------
	Name: ConVarB
-----------------------------------------------------------]]
function PANEL:SetConVarB( cvar )
	self.m_ConVarB = cvar
end

--[[---------------------------------------------------------
	Name: SetConVarA
-----------------------------------------------------------]]
function PANEL:SetConVarA( cvar )
	self.m_ConVarA = cvar
	self:SetAlphaBar( cvar != nil )
end

--[[---------------------------------------------------------
	Name: PerformLayout
-----------------------------------------------------------]]
function PANEL:PerformLayout( x, y )

	local h, s, v = ColorToHSV( self.HSV:GetBaseRGB() )
	self.RGB.LastY = ( 1 - h / 360 ) * self.RGB:GetTall()

end

--[[---------------------------------------------------------
	Name: Paint
-----------------------------------------------------------]]
function PANEL:Paint()
	-- Invisible background!
end

--[[---------------------------------------------------------
	Name: TranslateValues ( Todo? )
-----------------------------------------------------------]]
function PANEL:TranslateValues( x, y )
	
end

--[[---------------------------------------------------------
	Name: SetColor
-----------------------------------------------------------]]
function PANEL:SetColor( color )
	local h, s, v = ColorToHSV( color )
	self.RGB.LastY = ( 1 - h / 360 ) * self.RGB:GetTall()

	self.HSV:SetColor( color )

	self:UpdateColor( color )
end


function PANEL:SetVector( vec )

	self:SetColor( Color( vec.x * 255, vec.y * 255, vec.z * 255, 255 ) )

end

--[[---------------------------------------------------------
	Name: SetBaseColor
-----------------------------------------------------------]]
function PANEL:SetBaseColor( color )
	self.HSV:SetBaseRGB( color )
	self.HSV:TranslateValues()
end


--[[---------------------------------------------------------
	Name: UpdateConVar
-----------------------------------------------------------]]
function PANEL:UpdateConVar( strName, strKey, color )

	if ( !strName ) then return end
	local col = color[strKey]

	RunConsoleCommand( strName, tostring( col ) )

	self[ 'ConVarOld'..strName ] = col
end

--[[---------------------------------------------------------
	Name: UpdateConVars
-----------------------------------------------------------]]
function PANEL:UpdateConVars( color )

	self.NextConVarCheck = SysTime() + 0.2

	self:UpdateConVar( self.m_ConVarR, 'r', color )
	self:UpdateConVar( self.m_ConVarG, 'g', color )
	self:UpdateConVar( self.m_ConVarB, 'b', color )
	self:UpdateConVar( self.m_ConVarA, 'a', color )

end

--[[---------------------------------------------------------
	Name: UpdateColor
-----------------------------------------------------------]]
function PANEL:UpdateColor( color )
	self.Alpha:SetBarColor( ColorAlpha( color, 255 ) )
	self.Alpha:SetValue( color.a / 255 )

	local r, g, b, a = color.r, color.g, color.b, color.a
	local r_old, g_old, b_old, a_old = self.txtR:GetValue(), self.txtG:GetValue(), self.txtB:GetValue(), self.txtA:GetValue()

	if ( r ~= r_old ) then
		self.txtR.notuserchange = true
		self.txtR:SetValue( r )
		self.txtR.notuserchange = nil
	end

	if ( g ~= g_old ) then
		self.txtG.notuserchange = true
		self.txtG:SetValue( g )
		self.txtG.notuserchange = nil
	end

	if ( b ~= b_old ) then
		self.txtB.notuserchange = true
		self.txtB:SetValue( b )
		self.txtB.notuserchange = nil
	end

	if ( a ~= a_old ) then
		self.txtA.notuserchange = true
		self.txtA:SetValue( a )
		self.txtA.notuserchange = nil
	end

	self:UpdateConVars( color )
	self:ValueChanged( color )

	self.m_Color = color
end

--[[---------------------------------------------------------
	Name: ValueChanged
-----------------------------------------------------------]]
function PANEL:ValueChanged( color )
	-- Override
end

--[[---------------------------------------------------------
	Name: GetColor
-----------------------------------------------------------]]
function PANEL:GetColor()

	self.m_Color.a = 255
	if ( self.Alpha:IsVisible() ) then
		self.m_Color.a = math.floor( self.Alpha:GetValue() * 255 )
	end

	return self.m_Color
end

function PANEL:GetVector()

	local col = self:GetColor();
	return Vector( col.r / 255, col.g / 255, col.b / 255 )

end

--[[---------------------------------------------------------
	Name: Think
-----------------------------------------------------------]]
function PANEL:Think()

	self:ConVarThink()

end

--[[---------------------------------------------------------
	Name: ConVarThink
-----------------------------------------------------------]]
function PANEL:ConVarThink()

	-- Don't update the convars while we're changing them!
	if ( input.IsMouseDown( MOUSE_LEFT ) ) then return end
	if ( self.NextConVarCheck > SysTime() ) then return end

	local r, changed_r = self:DoConVarThink( self.m_ConVarR )
	local g, changed_g = self:DoConVarThink( self.m_ConVarG )
	local b, changed_b = self:DoConVarThink( self.m_ConVarB )
	local a, changed_a = 255, false

	if ( self.m_ConVarA ) then 
		a, changed_a = self:DoConVarThink( self.m_ConVarA, 'a' )
	end

	if ( changed_r or changed_g or changed_b or changed_a ) then
		self:SetColor( Color( r, g, b, a ) )
	end
end

--[[---------------------------------------------------------
	Name: DoConVarThink
-----------------------------------------------------------]]
function PANEL:DoConVarThink( convar )

	if ( !convar ) then return end

	local fValue = GetConVarNumber( convar )
	local fOldValue = self[ 'ConVarOld'..convar ]
	if ( fOldValue && fValue == fOldValue ) then return fOldValue, false end

	self[ 'ConVarOld'..convar ] = fValue

	return fValue, true

end

--[[---------------------------------------------------------
	Name: GenerateExample
-----------------------------------------------------------]]
function PANEL:GenerateExample( ClassName, PropertySheet, Width, Height )

	local ctrl = vgui.Create( ClassName )
		ctrl:SetSize( 256, 256 )

	PropertySheet:AddSheet( ClassName, ctrl, nil, true, true )

end

derma.DefineControl( "DColorMixer", "", PANEL, "DPanel" )