local idx = 1;
local numChoices = 4;

-- determine user's color
local UserColor = ColorToHSV( GetThemeColor() );

local userH = UserColor.Hue;
local userS = UserColor.Sat;
local userV = UserColor.Value;
local userA = 1;

local sliderLeft  = SCREEN_CENTER_X-252;
local sliderRight = SCREEN_CENTER_X+252;

local holdMovesByFull = 5;

local moveByClamped = 0.01;
local holdMovesByClamped = 0.1;

local t = Def.ActorFrame{
	--[[ output values ]]
	Def.Quad{
		InitCommand=cmd(CenterX;y,SCREEN_TOP+64;zoomto,SCREEN_WIDTH*0.9,28;diffuse,color("1,1,1,0.45");fadeleft,0.15;faderight,0.15;diffusebottomedge,color("0.8,0.8,0.8,0.45"));
	};
	
	AutoText("frutiger")..{
		Name="HueText";
		InitCommand=cmd(x,SCREEN_CENTER_X*0.5;y,SCREEN_TOP+64;shadowlength,1;NoStroke);
	};
	
	AutoText("frutiger")..{
		Name="SatText";
		InitCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_TOP+64;shadowlength,1;NoStroke);
	};
	
	AutoText("frutiger")..{
		Name="ValText";
		InitCommand=cmd(x,SCREEN_CENTER_X*1.5;y,SCREEN_TOP+64;shadowlength,1;NoStroke);
	};
	
	AutoText("frutiger")..{
		Name="ColorHexText";
		InitCommand=cmd(x,SCREEN_CENTER_X*0.25;y,SCREEN_TOP+144;shadowlength,1;diffuse,color("#FFFFFF");zoom,0.8;NoStroke);
	};
	
	AutoText("frutiger")..{
		Name="ColorRGBANormalText";
		InitCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_TOP+144;shadowlength,1;diffuse,color("#FFFFFF");zoom,0.8;NoStroke);
	};
	
	AutoText("frutiger")..{
		Name="ColorRGBAText";
		InitCommand=cmd(x,SCREEN_CENTER_X*1.75;y,SCREEN_TOP+144;shadowlength,1;diffuse,color("#FFFFFF");zoom,0.8;NoStroke);
	};
	
	-- outline
	Def.Quad{
		InitCommand=cmd(CenterX;y,SCREEN_TOP+104;zoomto,(SCREEN_WIDTH*0.8)+2,32+2;diffuse,color("0,0,0,1"));
	};
	-- color
	Def.Quad{
		Name="ColorPreview";
		InitCommand=cmd(CenterX;y,SCREEN_TOP+104;zoomto,(SCREEN_WIDTH*0.8),32);
	};
	--[[ /output values ]]
	
	--[[ part 1: hue bar (0-360) ]]
	LoadActor("_hue")..{
		InitCommand=cmd(CenterX;y,SCREEN_CENTER_Y*0.75);
		HSVFocusChangedMessageCommand=function(self,params)
			if params.NewIndex == 0 then
				idx = 1;
				
				self:finishtweening();
				self:accelerate(0.2);
				self:diffuse( color("1,1,1,1") );
			else
				self:finishtweening();
				self:accelerate(0.2);
				self:diffuse( color("0.5,0.5,0.5,1") );
			end;
		end;
	};
	
	Def.ActorFrame{
		Name="HueSlider";
		InitCommand=function(self)
			self:x( scale(userH, 0, 360, sliderLeft, sliderRight) );
			self:y(SCREEN_CENTER_Y*0.75);
		end;
		
		CodeMessageCommand=function(self,params)
			if idx == 1 then
				if params.Name == "MoveLeft" then
					if( userH > 0 ) then
						userH = userH - 1;
					end;
				end;
				
				if params.Name == "MoveRight" then
					if( userH < 360 ) then
						userH = userH + 1;
					end;
				end;
				
				if params.Name == "HoldLeft" then
					if( (userH - holdMovesByFull) > 0 ) then
						userH = userH - holdMovesByFull;
					else userH = 0;
					end;
				end;
				
				if params.Name == "HoldRight" then
					if( (userH + holdMovesByFull) < 360 ) then
						userH = userH + holdMovesByFull;
					else userH = 360;
					end;
				end;
				
				self:x( scale(userH, 0, 360, sliderLeft, sliderRight) );
			end;
		end;
		
		Def.Quad{
			Name="HueSliderBG";
			InitCommand=cmd(zoomto,8,32;diffuse,color("0,0,0,1"));
		};
		
		Def.Quad{
			Name="HueSliderProper";
			InitCommand=cmd(zoomto,6,30;diffuse,color("0.8,0.8,0.8,1");diffusetopedge,color("1,1,1,1");diffusebottomedge,color("0.5,0.5,0.5,1"));
		};
	};
	--[[ /part 1: hue bar ]]
	
	--[[ part 2: sat bar (0-1) ]]
	Def.Quad{
		Name="SaturationBar";
		InitCommand=cmd(CenterX;CenterY;zoomto,SCREEN_WIDTH*0.8,32);
		HSVFocusChangedMessageCommand=function(self,params)
			if params.NewIndex == 1 then
				idx = 2;
				
				self:finishtweening();
				self:accelerate(0.2);
				self:diffuse( color("1,1,1,1") );
			else
				self:finishtweening();
				self:accelerate(0.2);
				self:diffuse( HSV(userH,userS,userV/2) );
			end;
		end;
	};
	
	Def.ActorFrame{
		Name="SatSlider";
		InitCommand=function(self)
			self:x( scale(userS, 0, 1, sliderLeft, sliderRight) );
			self:y(SCREEN_CENTER_Y);
		end;
		
		CodeMessageCommand=function(self,params)
			if idx == 2 then
				if params.Name == "MoveLeft" then
					if( userS > 0 ) then
						userS = userS - moveByClamped;
					end;
				end;
				
				if params.Name == "MoveRight" then
					if( userS < 1 ) then
						userS = userS + moveByClamped;
					end;
				end;
				
				if params.Name == "HoldLeft" then
					if( (userS - holdMovesByClamped) > 0 ) then
						userS = userS - holdMovesByClamped;
					else userS = 0;
					end;
				end;
				
				if params.Name == "HoldRight" then
					if( (userS + holdMovesByClamped) < 1 ) then
						userS = userS + holdMovesByClamped;
					else userS = 1;
					end;
				end;
				
				self:x( scale(userS, 0, 1, sliderLeft, sliderRight) );
			end;
		end;
		
		Def.Quad{
			Name="SatSliderBG";
			InitCommand=cmd(zoomto,8,32;diffuse,color("0,0,0,1"));
		};
		
		Def.Quad{
			Name="SatSliderProper";
			InitCommand=cmd(zoomto,6,30;diffuse,color("0.8,0.8,0.8,1");diffusetopedge,color("1,1,1,1");diffusebottomedge,color("0.5,0.5,0.5,1"));
		};
	};
	--[[ /part 2: sat bar ]]
	
	--[[ part 3: val bar (0-1) ]]
	Def.Quad{
		Name="ValueBar";
		InitCommand=cmd(CenterX;y,SCREEN_CENTER_Y*1.25;zoomto,SCREEN_WIDTH*0.8,32);
		HSVFocusChangedMessageCommand=function(self,params)
			if params.NewIndex == 2 then
				idx = 3;
				
				self:finishtweening();
				self:accelerate(0.2);
				self:diffuse( color("0.01,0.01,0.01,1") );
			else
				self:finishtweening();
				self:accelerate(0.2);
				self:diffuse( color("0,0,0,1") );
			end;
		end;
	};
	
	Def.ActorFrame{
		Name="ValSlider";
		InitCommand=function(self)
			self:x( scale(userV, 0, 1, sliderLeft, sliderRight) );
			self:y(SCREEN_CENTER_Y*1.25);
		end;
		
		CodeMessageCommand=function(self,params)
			if idx == 3 then
				if params.Name == "MoveLeft" then
					if( userV > 0 ) then
						userV = userV - moveByClamped;
					end;
				end;
				
				if params.Name == "MoveRight" then
					if( userV < 1 ) then
						userV = userV + moveByClamped;
					end;
				end;
				
				if params.Name == "HoldLeft" then
					if( (userV - holdMovesByClamped) > 0 ) then
						userV = userV - holdMovesByClamped;
					else userV = 0;
					end;
				end;
				
				if params.Name == "HoldRight" then
					if( (userV + holdMovesByClamped) < 1 ) then
						userV = userV + holdMovesByClamped;
					else userV = 1;
					end;
				end;
				
				self:x( scale(userV, 0, 1, sliderLeft, sliderRight) );
			end;
		end;
		
		Def.Quad{
			Name="ValSliderBG";
			InitCommand=cmd(zoomto,8,32;diffuse,color("0,0,0,1"));
		};
		
		Def.Quad{
			Name="ValSliderProper";
			InitCommand=cmd(zoomto,6,30;diffuse,color("0.8,0.8,0.8,1");diffusetopedge,color("1,1,1,1");diffusebottomedge,color("0.5,0.5,0.5,1"));
		};
	};
	--[[ /part 3: val bar ]]
};

local function round(val, places)
	if (places) then
		return math.floor( (val * 10^places) + 0.5) / (10^places);
	else
		return math.floor(val+0.5);
	end;
end;

function UpdateHSV(self)
	local CurrentColor = {
		Hue = userH,
		Sat = userS,
		Value = userV,
		Alpha = userA
	};
	
	userH = round(userH, 2);
	userS = round(userS, 2);
	userV = round(userV, 2);
	
	local c = self:GetChildren();
	c.HueText:settext("Hue: " .. userH);
	c.SatText:settext("Sat: " .. userS);
	c.ValText:settext("Val: " .. userV);
	
	c.HueText:diffuse( HSVA(userH,1,1,1) );
	c.SatText:diffuse( HSVA(userH,userS,1,1) );
	c.ValText:diffuse( HSVA(userH,1,userV,1) );
	
	--c.ColorPreview:diffuse( HSV(userH,userS,userV) );
	c.ColorPreview:diffuse( HSVA(userH,userS,userV,userA) );
	
	-- focus diffusing
	if idx ~= 2 then -- Saturation
		c.SaturationBar:diffuse( HSVA(userH,0,userV/2,1) );
		c.SaturationBar:diffuserightedge( HSVA(userH,1,userV/2,1) );
	else
		c.SaturationBar:diffuse( HSVA(userH,0,userV,1) );
		c.SaturationBar:diffuserightedge( HSVA(userH,1,userV,1) );
	end;
	
	if idx ~= 3 then -- Value
		c.ValueBar:diffuserightedge( HSVA(userH,userS,0.5,1) );
	else
		c.ValueBar:diffuserightedge( HSVA(userH,userS,1,1) );
	end;
	
	-- colortext
	local color = HSVToColor( CurrentColor );
	local colorX = ColorToHex(color);
	
	--[[ default (0-1) ]]
	local r = color[1];
	local g = color[2];
	local b = color[3];
	local a = color[4];
	
	r = round(r, 2);
	g = round(g, 2);
	b = round(b, 2);
	
	local rgba = "("..r..","..g..","..b..","..a..")";
	c.ColorRGBAText:settext(rgba);
	
	--[[ normalized (0-255) ]]
	local rN = scale(color[1], 0, 1, 0, 255);
	local gN = scale(color[2], 0, 1, 0, 255);
	local bN = scale(color[3], 0, 1, 0, 255);
	local aN = scale(color[4], 0, 1, 0, 255);
	
	-- normalize down to ints
	rN = math.ceil(rN);
	gN = math.ceil(gN);
	bN = math.ceil(bN);
	aN = math.ceil(aN);
	
	local rgbaN = "("..rN..","..gN..","..bN..","..aN..")";
	c.ColorRGBANormalText:settext(rgbaN);
	
	--[[ hex ]]
	local rX = colorX[1];
	local gX = colorX[2];
	local bX = colorX[3];
	local aX = colorX[4];
	
	c.ColorHexText:settext("#"..colorX);
	
	MESSAGEMAN:Broadcast( "UpdateBackgroundColor", { Color = HSVA(userH,userS,userV,userA) } );
end;

t.InitCommand=cmd(SetUpdateFunction,UpdateHSV);

return t;