--	RangeRecolor
--	by Feshy, CrowGoblin

BINDING_HEADER_RANGERECOLOR = "RangeRecolor";

local RangeRecolorName = "RangeRecolor";
local RangeRecolorVersion = 3.0;

local	RangeRecolorNormal = { r = 1.0, g = 1.0, b = 1.0 };

local MyAddonDetails = {
	name=RangeRecolorName,
	version=RangeRecolorVersion,
	releaseDate="May 27, 2006",
	author="CrowGoblin, Feshy",
	category=MYADDONS_CATEGORY_BARS,
	optionsframe="RangeRecolorOptions"
};

local MyAddonHelp = {};
MyAddonHelp[1] = "Options:\n==========\n\n\nEnable RangeRecolor\n----------\n\n(Checked)   Enables all RangeRecolor features (Default)\n\n(Unchecked)   Disables RangeRecolor\n\n\nRange color has priority over mana color\n----------\n\n(Checked)   If a target is out of range and the player is out of mana, colors the action bar with the out of range color.\n\n(Unchecked)   If the target is out of range, and the player is out of mana, colors the action bar with the out of mana color. (Default)";

function RangeRecolorAction_OnLoad()
	this:RegisterEvent("VARIABLES_LOADED");
	-- Add RangeRecolor frame to the UIPanelWindows list
	UIPanelWindows["RangeRecolorOptions"] = {area = "center", pushable = 0};
	-- Add RangeRecolor slash commands
	SlashCmdList["RangeRecolorCMD"] = RangeRecolor_Command;
	SLASH_RangeRecolorCMD1 = "/rr";
	
end

function RangeRecolorOptions_Defaults()
	RangeRecolorEnabled = true;
	RangeRecolorRangePriority = false;
	RangeRecolorOOR = { r = 0.8, g = 0.1, b = 0.1 };
	RangeRecolorOOM = { r = 0.5, g = 0.5, b = 1.0 };
	
	RangeRecolorOptions_Show()
end

function SetSwatch(ColorSet, ID)
	local button = getglobal("RangeColor"..ID);
	local swatch = getglobal("RangeColor"..ID.."_SwatchTexture");
	local border = getglobal("RangeColor"..ID.."_BorderTexture");

	button.a = 1.0;
	button.r = ColorSet.r;
	button.g = ColorSet.g;
	button.b = ColorSet.b;
	swatch:SetVertexColor(ColorSet.r, ColorSet.g, ColorSet.b);
	border:SetVertexColor(ColorSet.r, ColorSet.g, ColorSet.b);

end

function SetCheckbox(name, checked)
	local ischecked;
	local button1 = getglobal(name);
	if (checked) then
		ischecked = 1;
	else
		ischecked = 0;
	end
	button1:SetChecked(checked);
end

function RangeRecolorOptions_Show()
	-- Set up checkboxes
	SetCheckbox("RangeRecolorOptionsFrame_CheckButton1", RangeRecolorEnabled);
	SetCheckbox("RangeRecolorOptionsFrame_CheckButton2", RangeRecolorRangePriority);
	
	-- Set up color swatches
	SetSwatch(RangeRecolorOOR, 1);
	SetSwatch(RangeRecolorOOM, 2);
	
end

function RangeRecolor_ColorCallback(id)
	if (1 == id) then
		RangeRecolorOOR.r, RangeRecolorOOR.g, RangeRecolorOOR.b  = ColorPickerFrame:GetColorRGB();
	elseif (2 == id) then
		RangeRecolorOOM.r, RangeRecolorOOM.g, RangeRecolorOOM.b  = ColorPickerFrame:GetColorRGB();
	else
	end
	RangeRecolorOptions_Show();
		
end

function RangeRecolor_OptionsCheckButtonOnClick(id)
	if(1 == id) then
		if (RangeRecolorEnabled) then
			RangeRecolorEnabled = false;
		else
			RangeRecolorEnabled = true;
		end
	elseif(2 == id) then
		if (RangeRecolorRangePriority) then
			RangeRecolorRangePriority = false;
		else
			RangeRecolorRangePriority = true;
		end
	end
end

function RangeRecolor_CancelColorCallback(id)
	if (1 == id) then
		RangeRecolorOOR.r = ColorPickerFrame.previousValues.r;
		RangeRecolorOOR.g = ColorPickerFrame.previousValues.g;
		RangeRecolorOOR.b = ColorPickerFrame.previousValues.b;
	elseif (2 == id) then
		RangeRecolorOOM.r = ColorPickerFrame.previousValues.r;
		RangeRecolorOOM.g = ColorPickerFrame.previousValues.g;
		RangeRecolorOOM.b = ColorPickerFrame.previousValues.b;
	else
	end
	RangeRecolorOptions_Show();
end

function RangeRecolorOptions_Hide()
	RangeRecolorOptions:Hide();
end

-- Command parser
	-- Command-line processing is not done now; all options set through menu atm.
function RangeRecolor_Command(msg)
	if (msg==nil) then
		msg = "";
	else
		RangeRecolorOptions:Show();
	end
end

local function SetHook(myFunction, HookFunc)
	if(myFunction) then
		local oldFunction = getglobal(HookFunc);
		local newFunction =
			function(e)
				oldFunction(e);
				myFunction(e);
			end
		setglobal(HookFunc, newFunction);
	end
end

function RangeRecolorAction_OnEvent(event)
	if ("VARIABLES_LOADED" == event) then
		-- Set Up Defaults
		if(RangeRecolorEnabled == nil) then
			RangeRecolorEnabled = true;
		end
		if(RangeRecolorOOR == nil) then
			RangeRecolorOOR = { r = 0.8, g = 0.1, b = 0.1 };
		end
		if(RangeRecolorOOM == nil) then
			RangeRecolorOOM = { r = 0.5, g = 0.5, b = 1.0 };
		end
		if(RangeRecolorRangePriority == nil) then
			RangeRecolorRangePriority = false;
		end
		RangeRecolorAction_Setup();
		
		local button, string;
		
		button = getglobal("RangeColor1"); 
		button.swatchFunc = function(x) RangeRecolor_ColorCallback(1) end;
		button.cancelFunc = function(x) RangeRecolor_CancelColorCallback(1) end;
		button.id = 1;
		button.disabled = nil;
		string = getglobal("RangeColor1Text");
		string:SetText("Colour for out-of-range\naction buttons");
		
		button = getglobal("RangeColor2"); 
		button.swatchFunc = function(x) RangeRecolor_ColorCallback(2) end;
		button.cancelFunc = function(x) RangeRecolor_CancelColorCallback(2) end;
		button.id = 2;
		button.disabled = nil;
		string = getglobal("RangeColor2Text");
		string:SetText("Colour for out-of-mana\naction buttons");
		
		button = getglobal("RangeRecolorOptionsFrame_CheckButton1");
		string = getglobal("RangeRecolorOptionsFrame_CheckButton1Text");
		string:SetText("Enable RangeRecolor");
		button.id = 1;
		
		button = getglobal("RangeRecolorOptionsFrame_CheckButton2");
		string = getglobal("RangeRecolorOptionsFrame_CheckButton2Text");
		string:SetText("Range color has priority\nover mana color");
		button.id = 2;
		
		
		if(myAddOnsFrame_Register) then
			myAddOnsFrame_Register(MyAddonDetails, MyAddonHelp);
		end
	end
end

function RangeRecolorAction_Setup()

	-- Hook Standard Buttons
	SetHook(RangeRecolorAction_OnUpdate, "ActionButton_OnUpdate");
	SetHook(RangeRecolorAction_UpdateUsable, "ActionButton_UpdateUsable");
	local hooks = "Standard Bar";

	-- CTMod
	if (type(CT_ActionButton_OnUpdate) == 'function') then
		SetHook(RangeRecolorAction_CT_OnUpdate, "CT_ActionButton_OnUpdate");
		SetHook(RangeRecolorAction_CT_UpdateUsable, "CT_ActionButton_UpdateUsable");
		hooks = hooks..", CT ToolBars";	
	end

	-- Gypsy
	if (type(Gypsy_ActionButtonOnUpdate) == 'function') then
		SetHook(RangeRecolorAction_OnUpdate, "Gypsy_ActionButtonOnUpdate");
		SetHook(RangeRecolorAction_UpdateUsable, "Gypsy_ActionButtonUpdateUsable");
		hooks = hooks..", Gypsy HotBar";
	end

	-- GhostBar
	if (type(GhostBar_ButtonOnUpdate) == 'function') then
		SetHook(RangeRecolorAction_OnUpdate, "GhostBar_ButtonOnUpdate");
		SetHook(RangeRecolorAction_UpdateUsable, "GhostBar_ButtonUpdateUsable");
		hooks = hooks..", GhostBar";	
	end

	-- PopBar
	if (type(PopBarButton_OnUpdate) == 'function') then
		SetHook(RangeRecolorAction_Pop_OnUpdate, "PopBarButton_OnUpdate");
		SetHook(RangeRecolorAction_Pop_UpdateUsable, "PopBarButton_UpdateUsable");
		hooks = hooks..", PopBar";	
	end

	-- Telo Sidebar
	if (type(SideBarButton_OnUpdate) == 'function') then
		SetHook(RangeRecolorAction_TSB_OnUpdate, "SideBarButton_OnUpdate");
		SetHook(RangeRecolorAction_TSB_UpdateUsable, "SideBarButton_UpdateUsable");
		hooks = hooks..", SideBar";	
	end

	-- Telo Bottombar
	if (type(BottomBarButton_OnUpdate) == 'function') then
		SetHook(RangeRecolorAction_TBB_OnUpdate, "BottomBarButton_OnUpdate");
		SetHook(RangeRecolorAction_TBB_UpdateUsable, "BottomBarButton_UpdateUsable");
		hooks = hooks..", BottomBar";	
	end

	-- FlexBar
	if (type(FlexBarButton_Update) == 'function') then
		SetHook(RangeRecolorAction_Flex_OnUpdate, "FlexBarButton_Update");
		SetHook(RangeRecolorAction_Flex_UpdateUsable, "FlexBarButton_UpdateUsable");
		hooks = hooks..", FlexBar";	
	end

	-- Discord ActionBars
	if (type(DAB_ActionButton_OnUpdate) == 'function') then
		SetHook(RangeRecolorAction_DAB_OnUpdate, "DAB_ActionButton_Update");
		hooks = hooks..", Discord ActionBars";	
	end

	if ( DEFAULT_CHAT_FRAME ) then
		DEFAULT_CHAT_FRAME:AddMessage(string.format("RangeRecolor loaded for: "..hooks),RangeRecolorOOR.r, RangeRecolorOOR.g, RangeRecolorOOR.b);
	end
end

local function SetColor(ColorSet, icon, normalTexture)
	icon:SetVertexColor (ColorSet.r, ColorSet.g, ColorSet.b);
	normalTexture:SetVertexColor (ColorSet.r, ColorSet.g, ColorSet.b);
end

local function RangeRecolorRecolorButton(button, buttonID)
	if (not RangeRecolorEnabled) then
		return;
	end
	local icon = getglobal(button:GetName().."Icon");
	local normalTexture = getglobal(button:GetName().."NormalTexture");
	local isUsable = IsUsableAction(buttonID);
	local inRange = IsActionInRange(buttonID);
	
	-- IsActionInRange returns nil in cases when range does not matter
	-- unfortunately, that means that when range is not a problem, if(inRange) 
	-- returns false (nil) So, fix that little oversight.
	if(0 == inRange) then 
		inRange = false;
	else
		inRange = true;
	end
	
	if(icon and normalTexture ) then
		-- in range and useable, so no color shading.
		if(inRange and isUsable) then
			SetColor(RangeRecolorNormal, icon, normalTexture);
		-- if it is useable, we know it is out of range (because the previous if eliminated the other case)
		elseif(isUsable) then
			SetColor(RangeRecolorOOR, icon, normalTexture);
		-- if it is in range, we know it is not useable (because the first if eliminated the other case)
		elseif(inRange) then
			SetColor(RangeRecolorOOM, icon, normalTexture);
		-- by here, we only have the possibility that it is both OOR and OOM, choose appropriately.
		elseif(RangeRecolorRangePriority) then
			SetColor(RangeRecolorOOR, icon, normalTexture);
		else
			SetColor(RangeRecolorOOM, icon, normalTexture);
		end
	end
end

local function CheckButton(button)
	if(not button) then
		button = this;
	end
end

function RangeRecolorAction_UpdateUsable(arg)
	local buttonID = ActionButton_GetPagedID(this);
	RangeRecolorRecolorButton(this, buttonID);
end

function RangeRecolorAction_CT_UpdateUsable(button)
	CheckButton(button);
	local buttonID = CT_ActionButton_GetPageID(button);
	RangeRecolorRecolorButton(button, buttonID);
end

function RangeRecolorAction_Pop_UpdateUsable(button)
	CheckButton(button);
	local buttonID = PopBarButton_GetPageID(button);
	RangeRecolorRecolorButton(button, buttonID);
end

function RangeRecolorAction_TSB_UpdateUsable(button)
	CheckButton(button);
	local buttonID = SideBarButton_GetPageID(button);
	RangeRecolorRecolorButton(button, buttonID);
end

function RangeRecolorAction_TBB_UpdateUsable(button)
	CheckButton(button);
	local buttonID = BottomBarButton_GetPageID(button);
	RangeRecolorRecolorButton(button, buttonID);
end

function RangeRecolorAction_Flex_UpdateUsable(button)
	CheckButton(button);
	local buttonID = FlexBarButton_GetID(button);
	RangeRecolorRecolorButton(button, buttonID);
end

function RangeRecolorAction_OnUpdate(elapsed)
	local buttonID = ActionButton_GetPagedID(this);
	RangeRecolorRecolorButton(this, buttonID);
end

function RangeRecolorAction_CT_OnUpdate(elapsed)
	local buttonID = CT_ActionButton_GetPageID(button);
	RangeRecolorRecolorButton(this, buttonID);
end

function RangeRecolorAction_Pop_OnUpdate(elapsed)
	local buttonID = PopBarButton_GetPageID(button);
	RangeRecolorRecolorButton(this, buttonID);
end

function RangeRecolorAction_TSB_OnUpdate(elapsed)
	local buttonID = SideBarButton_GetPageID(button);
	RangeRecolorRecolorButton(this, buttonID);
end

function RangeRecolorAction_TBB_OnUpdate(elapsed)
	local buttonID = BottomBarButton_GetPageID(button);
	RangeRecolorRecolorButton(this, buttonID);
end

function RangeRecolorAction_Flex_OnUpdate(elapsed)
	local buttonID = FlexBarButton_GetID(button);
	RangeRecolorRecolorButton(this, buttonID);
end

function RangeRecolorAction_DAB_OnUpdate(elapsed)
	local buttonID = FlexBarButton_GetID(button);
	RangeRecolorRecolorButton(this, buttonID);
end