--[[
		FancyBar v1.6
				by Arbi

		Added to 12 extra buttons that unused by Blizzard action bars.

		$Date: 2007-07-08 11:53:27 +0900 (Sun, 8 Jul 2007) $

		Change Log:
			v 1.0 - Initial release
			v 1.1 - Added to SideBar Shape
			v 1.2 - Added to Hide buttons option
			v 1.3 - Removed Cosmos dependency
			        Added to center bar (twin tower shape)
			v 1.4 - Fixed to scale not saved
				Support to CooldownCount for FancyBar
			v 1.5 - No longer use clickbinder. now use Blizzard's keybinding UI.
				Added to cooldown count text.
			v 1.6 - Fixed for Moonkin/Shadowform action bar page sharing issue.
			v 1.7 - Fixed action button id sharing issue that between moonkin and tree of life
]]--

FancyBar_On = 0;
FancyBar_Lock = 0;
FancyBar_Vertical = 0;
FancyBar_Row = 1;
FancyBar_Scale = 1;
CenterBar_On = 0;
CenterBar2_On = 0;
SideBar_On = 0;
FancyBar_SideBar_VerticalOffset = 120;
FancyBar_Center_HorizonOffset = 170;

FancyBar_HideKeys = 0;
FancyBar_HideKeyMod = 0;
FancyBar_HideEmpty = 0;
FancyBar_HideCooldown = 0;
FancyBar_LeftMovePartyMemberFrames = 0;

local FancyBar_ConvertDone = false;
local FancyBar_LoadOnce = false;

function FancyBar_OnLoad()
	this:RegisterEvent("VARIABLES_LOADED");
	this:RegisterEvent("PLAYER_ENTERING_WORLD");
	this:RegisterEvent("PLAYER_LEAVING_WORLD");

	if ( Cosmos_RegisterConfiguration ) then
		FancyBar_RegisterCosmos();
	else
		FancyBar_Register();
	end
end

function FancyBar_OnEvent()
	if ( event == "VARIABLES_LOADED" ) then
		FancyBar_Initialize();
		if ( not Cosmos_RegisterConfiguration ) then
			FancyBar_Toggle(FancyBar_On);
			FancyBar_SetLock(FancyBar_Lock);
			FancyBar_SetVertical(FancyBar_Vertical);
		end
	elseif ( event == "PLAYER_ENTERING_WORLD" ) then
		this:RegisterEvent("UPDATE_BINDINGS")
		if ( not FancyBar_ConvertDone ) then
			FancyBar_ConvertBindings();
			FancyBar_RegisterBindings();
			FancyBar_ConvertDone = true;
		end
		if ( not FancyBar_LoadOnce ) then
			FancyBar_ChangeIDs();
			FancyBar_LoadOnce = true;
		end
	elseif ( event == "PLAYER_ALIVE" ) then
		FancyBar_ScanDruidtalents();
	elseif ( event == "UPDATE_BINDINGS" ) then
		FancyBar_RegisterBindings();
	elseif ( event == "PLAYER_LEAVING_WORLD" ) then
		this:UnregisterEvent("UPDATE_BINDINGS")
	end
end

function FancyBar_Initialize()
	local height, width;

	for i = 1, 12 do
		local action = 108 + i;
		local button = getglobal("FancyBarButton"..i);
		button:SetAttribute("type", "action");
		button:SetAttribute("action", action);
		button:SetAttribute("checkselfcast", true);
		button:SetAttribute("useparent-unit", true);
		button:SetAttribute("useparent-statebutton", true);
		height = button:GetHeight() + 5;
		width = button:GetWidth() + 5;
		button:SetPoint("BOTTOMLEFT", (i - 1) * width, 0);
		getglobal(button:GetName().."Cooldown"):SetFrameLevel(2);
		getglobal(button:GetName().."CooldownCount"):Show();
	end
	if ( not Cosmos_RegisterConfiguration ) then
		FancyBar_SetScale(1, FancyBar_Scale);
	end
	FancyBarButton_UpdateHidingEmptySlots();
end

function FancyBar_ChangeIDs()
	local _, class = UnitClass("player");
	if ( class == "DRUID" or class == "PRIEST" ) then
		if ( class == "DRUID" ) then
			this:RegisterEvent("PLAYER_ALIVE");
		end
		druid_or_priest = true;
		for i = 1, 12 do
			local action = 84 + i;
			local button = getglobal("FancyBarButton"..i);
			button:SetAttribute("action", action);
		end
	end
end

function FancyBar_ScanDruidtalents()
	local _, class = UnitClass("player");
	if ( class == "DRUID" ) then
		local _, _, _, _, current = GetTalentInfo(3, 20);
		if ( current == 1 ) then
			druid_or_priest = false;
			for i = 1, 12 do
				local action = 108 + i;
				local button = getglobal("FancyBarButton"..i);
				button:SetAttribute("action", action);
			end
			this:UnregisterEvent("PLAYER_ALIVE");
		end
	end
end

function FancyBar_RegisterCosmos()
	if ( Cosmos_RegisterConfiguration ) then
		Cosmos_RegisterConfiguration("COS_FANCYBAR", "SECTION", FANCYBAR_SEP, FANCYBAR_SEP_INFO );
		Cosmos_RegisterConfiguration("COS_FANCYBAR_HEADER", "SEPARATOR", FANCYBAR_SEP, FANCYBAR_SEP_INFO );
		Cosmos_RegisterConfiguration("COS_FANCYBAR_ENABLE", "CHECKBOX",
			FANCYBAR_ENABLE, 
			FANCYBAR_ENABLE_INFO,
			FancyBar_Toggle,
			0
			);
		Cosmos_RegisterConfiguration("COS_FANCYBAR_HIDEEMPTY", "CHECKBOX",
			FANCYBAR_CONFIG_HIDE_EMPTY,
			FANCYBAR_CONFIG_HIDE_EMPTY_INFO,
			FancyBar_SetHideEmpty,
			FancyBar_HideEmpty
			);
		Cosmos_RegisterConfiguration("COS_FANCYBAR_LOCK", "CHECKBOX",
			FANCYBAR_LOCK,
			FANCYBAR_LOCK_INFO,
			FancyBar_SetLock,
			FancyBar_Lock
			);
		Cosmos_RegisterConfiguration("COS_FANCYBAR_COOLDOWN", "CHECKBOX",
			FANCYBAR_COOLDOWN,
			FANCYBAR_COOLDOWN_INFO,
			FancyBar_SetCooldown,
			FancyBar_HideCooldown
			);
		Cosmos_RegisterConfiguration("COS_FANCYBAR_VERTICAL", "CHECKBOX",
			FANCYBAR_VERTICAL,
			FANCYBAR_VERTICAL_INFO,
			FancyBar_SetVertical,
			FancyBar_Vertical
			);
		Cosmos_RegisterConfiguration(
			"COS_FANCYBAR_ROW", -- CVAr
			"SLIDER",
			FANCYBAR_ROW,
			"",
			FancyBar_SetRow,
			0,
			FancyBar_Row,			--Default Value
			1,			--Min value
			3,			--Max value
			"",			--Slider Text
			1,				--Slider Increment
			1,				--Slider state text on/off
			"",				--Slider state text append
			1				--Slider state text multiplier
			);
		Cosmos_RegisterConfiguration(
			"COS_FANCYBAR_SCALE", -- CVAr
			"SLIDER",
			FANCYBAR_SCALE,
			"",
			FancyBar_SetScale,
			0,
			FancyBar_Scale,			--Default Value
			0.8,			--Min value
			1,			--Max value
			"",			--Slider Text
			0.01,				--Slider Increment
			1,				--Slider state text on/off
			"",				--Slider state text append
			1				--Slider state text multiplier
			);
		Cosmos_RegisterConfiguration("COS_FANCYBAR_CHANGEFANCYBAR",
			"BUTTON",
			FANCYBAR_CHANGE_FANCYBAR,
			"",
			FancyBar_ChangeFancyBar,
			0,
			0,
			0,
			0,
			FANCYBAR_CHANGE_FANCYBAR_NAME
			);
		Cosmos_RegisterConfiguration("COS_FANCYBAR_CENTER_HEADER", "SEPARATOR", FANCYBAR_CENTER_SEP, FANCYBAR_CENTER_SEP_INFO );
		Cosmos_RegisterConfiguration("COS_FANCYBAR_CHANGECENTERBAR",
			"BUTTON",
			FANCYBAR_CHANGE_CENTERBAR,
			"",
			FancyBar_ChangeCenterBar,
			0,
			0,
			0,
			0,
			FANCYBAR_CHANGE_CENTERBAR_NAME
			);
		Cosmos_RegisterConfiguration("COS_FANCYBAR_CHANGECENTERBAR2",
			"BUTTON",
			FANCYBAR_CHANGE_CENTERBAR2,
			"",
			FancyBar_ChangeCenterBar2,
			0,
			0,
			0,
			0,
			FANCYBAR_CHANGE_CENTERBAR_NAME
			);
		Cosmos_RegisterConfiguration(
			"COS_FANCYBAR_HORIZONOFFSET", -- CVAr
			"SLIDER",
			FANCYBAR_CENTER_HORIZON,
			"",
			FancyBar_Center_UpdateOffset,
			0,
			FancyBar_Center_HorizonOffset,		--Default Value
			-550,			--Min value
			550,			--Max value
			FANCYBAR_CENTER_HORIZON_OFFSET,		--Slider Text
			1,				--Slider Increment
			1,				--Slider state text on/off
			"",				--Slider state text append
			1				--Slider state text multiplier
			);
		Cosmos_RegisterConfiguration("COS_FANCYBAR_SIDEBAR_HEADER", "SEPARATOR", FANCYBAR_SIDEBAR_SEP, FANCYBAR_SIDEBAR_SEP_INFO );
		Cosmos_RegisterConfiguration("COS_FANCYBAR_CHANGESIDEBAR",
			"BUTTON",
			FANCYBAR_CHANGE_SIDEBAR,
			"",
			FancyBar_ChangeSideBar,
			0,
			0,
			0,
			0,
			FANCYBAR_CHANGE_SIDEBAR_NAME
			);
		Cosmos_RegisterConfiguration(
			"COS_FANCYBAR_SIDEBAR_VERTICALOFFSET", -- CVAr
			"SLIDER",
			FANCYBAR_SIDEBAR_VERTICAL,
			"",
			FancyBar_SideBar_UpdateOffset,
			0,
			FancyBar_SideBar_VerticalOffset,		--Default Value
			0,			--Min value
			300,			--Max value
			FANCYBAR_SIDEBAR_VERTICAL_OFFSET,		--Slider Text
			1,				--Slider Increment
			1,				--Slider state text on/off
			"",				--Slider state text append
			1				--Slider state text multiplier
			);
	end
end

function FancyBar_Register()
	-- Register our slash command
	SLASH_FANCYBAR1 = "/fancybar";
	SLASH_FANCYBAR2 = "/fbar";
	SlashCmdList["FANCYBAR"] = function(msg)
		FancyBar_SlashCommandHandler(msg);
	end
end

function FancyBar_Usage()
	local index = 0;
	local value = getglobal("FANCYBAR_HELP_TEXT"..index);
	while( value ) do
		DEFAULT_CHAT_FRAME:AddMessage(value);
		index = index + 1;
		value = getglobal("FANCYBAR_HELP_TEXT"..index);
	end
end

function FancyBar_SlashCommandHandler(msg)
	if( not msg or msg == "" ) then
		-- FancyBar Help Text
		FancyBar_Usage();
	else
		local _, _, command, args = string.find(msg, "^(%w+)%s*(.*)$");
		if ( command == "on" ) then
			FancyBar_On = 1;
			FancyBar_Toggle(1);
			FancyBar_SetLock(FancyBar_Lock);
		elseif ( command == "off" ) then
			FancyBar_On = 0;
			FancyBar_Toggle(0);
			FancyBar_SetLock(FancyBar_Lock);
		elseif ( command == "flex" ) then
			FancyBar_ChangeFancyBar();
			FancyBar_SetLock(FancyBar_Lock);
		elseif ( command == "center1" ) then
			FancyBar_ChangeCenterBar();
			FancyBar_SetLock(FancyBar_Lock);
		elseif ( command == "center2" ) then
			FancyBar_ChangeCenterBar2();
			FancyBar_SetLock(FancyBar_Lock);
		elseif ( command == "sidebar" ) then
			FancyBar_ChangeSideBar();
		elseif ( command == "offset" and args ) then
			if ( CenterBar_On == 1 or CenterBar2_On == 1 ) then
				FancyBar_Center_UpdateOffset(1, args);
			elseif ( SideBar_On == 1 ) then
				FancyBar_SideBar_UpdateOffset(1, args);
			end
		elseif ( command == "lock" ) then
			if ( FancyBar_Lock == 1 ) then
				FancyBar_Lock = 0;
				FancyBar_SetLock(FancyBar_Lock);
			else
				FancyBar_Lock = 1;
				FancyBar_SetLock(FancyBar_Lock);
			end
		elseif ( command == "cooldown" ) then
			if ( FancyBar_HideCooldown == 1 ) then
				FancyBar_HideCooldown = 0;
			else
				FancyBar_HideCooldown = 1;
			end
		elseif ( command == "hidden" ) then
			if ( FancyBar_HideEmpty == 1 ) then
				FancyBar_SetHideEmpty(0);
			else
				FancyBar_SetHideEmpty(1);
			end
		elseif ( command == "scale" ) then
			FancyBar_SetScale(1, args);
		elseif ( command == "reset" ) then
		else
			-- FancyBar Help Text
			FancyBar_Usage();
		end
	end
end

function FancyBar_ConvertBindings()
	for i=1,12 do
		local key1, key2 = GetBindingKey("CLICK FancyBarButton"..i..":LeftButton");
		if key1 then SetBinding(key1, "FANCYBARACTIONBUTTON" .. i); end
		if key2 then SetBinding(key2, "FANCYBARACTIONBUTTON" .. i); end
	end
	SaveBindings(GetCurrentBindingSet());
end

function FancyBar_RegisterBindings()
	ClearOverrideBindings(FancyBar);
	for i=1, 12 do
		local key1, key2 = GetBindingKey("FANCYBARACTIONBUTTON"..i)
		if key1 then SetOverrideBindingClick(FancyBar, false, key1, "FancyBarButton" .. i); end
		if key2 then SetOverrideBindingClick(FancyBar, false, key2, "FancyBarButton" .. i); end
	end
end

function FancyBar_Toggle(toggle)
	if (toggle == 1) then
		if ( CenterBar_On == 1 ) then
			FancyBar_ChangeCenterBar();
		elseif ( CenterBar2_On == 1 ) then
			FancyBar_ChangeCenterBar2();
		elseif ( SideBar_On == 1 ) then
			FancyBar_ChangeSideBar();
		else
			FancyBar_ChangeFancyBar();
		end
		FancyBar:Show();
	else
		FancyBar:Hide();
	end
end

function FancyBar_SetLock(toggle)
	if (toggle == 1 or not FancyBar:IsVisible() or SideBar_On == 1) then
		FancyBar_Lock = 1;
		FancyBarDragButton:Hide();
	else
		FancyBar_Lock = 0;
		FancyBarDragButton:Show();
	end
end

function FancyBar_SetCooldown(toggle)
	if (toggle == 1 ) then
		FancyBar_HideCooldown = 1;
	else
		FancyBar_HideCooldown = 0;
	end
end

function FancyBar_SetVertical(toggle)
	if ( CenterBar_On == 1 or CenterBar2_On == 1 or SideBar_On == 1 ) then
		return;
	end
	if ( toggle == 1 ) then
		FancyBar_Vertical = 1;
		FancyBar_SetupBar(1);
	else
		FancyBar_Vertical = 0;
		FancyBar_SetupBar(0);
	end
end

function FancyBar_SetRow(check, value)
	if ( CenterBar_On == 1 or CenterBar2_On == 1 or SideBar_On == 1 ) then
		return;
	end
	FancyBar_Row = value;
	FancyBar_SetupBar(nil, value);
end

function FancyBar_SetScale(check, value)
	FancyBar_Scale = value;
	FancyBar:SetScale(value);
end

function FancyBar_ChangeShape()
	if ( FancyBar_Vertical == 1 ) then
		if ( Cosmos_SetCVar ) then
			Cosmos_SetCVar("COS_FANCYBAR_VERTICAL_X", 0);
		end
		FancyBar_Vertical = 0;
		FancyBar_SetupBar(0);
	else
		if ( Cosmos_SetCVar ) then
			Cosmos_SetCVar("COS_FANCYBAR_VERTICAL_X", 1);
		end
		FancyBar_Vertical = 1;
		FancyBar_SetupBar(1);
	end
end

function FancyBar_ChangeRow()
	FancyBar_Row = FancyBar_Row + 1;
	if ( FancyBar_Row > 3 ) then
		FancyBar_Row = 1;
	end
	if ( Cosmos_SetCVar ) then
		Cosmos_SetCVar("COS_FANCYBAR_ROW", FancyBar_Row);
	end
	FancyBar_SetupBar(nil, FancyBar_Row);
end

function FancyBar_SetupBar(vertical, row)
	if ( CenterBar_On == 1 or CenterBar2_On == 1 or SideBar_On == 1 ) then
		return;
	end
	if ( not vertical ) then
		vertical = FancyBar_Vertical;
	end
	if ( not row ) then
		row = FancyBar_Row;
	end
	if ( vertical == 0 ) then
		FancyBarButton1:ClearAllPoints();
		getglobal("FancyBarButton1"):SetPoint("LEFT", "FancyBarDragButton", "RIGHT", 6, 0);
		for i = 2, 12 do
			local col = i-1;
			getglobal("FancyBarButton"..i):ClearAllPoints();
			if ( row == 2 and col == 6 ) then
				getglobal("FancyBarButton"..i):SetPoint("BOTTOM", "FancyBarButton"..i-6, "TOP", 0, 6);
			elseif ( row == 3 and ( col == 4 or col == 8 ) ) then
				getglobal("FancyBarButton"..i):SetPoint("BOTTOM", "FancyBarButton"..i-4, "TOP", 0, 6);
			else
				getglobal("FancyBarButton"..i):SetPoint("LEFT", "FancyBarButton"..col, "RIGHT", 6, 0);
			end
		end
	else
		FancyBarButton1:ClearAllPoints();
		getglobal("FancyBarButton1"):SetPoint("TOP", "FancyBarDragButton", "BOTTOM", 0, -6);
		for i = 2, 12 do
			local col = i-1;
			getglobal("FancyBarButton"..i):ClearAllPoints();
			if ( row == 2 and col == 6 ) then
				getglobal("FancyBarButton"..i):SetPoint("LEFT", "FancyBarButton"..i-6, "RIGHT", 6, 0);
			elseif ( row == 3 and ( col == 4 or col == 8 ) ) then
				getglobal("FancyBarButton"..i):SetPoint("LEFT", "FancyBarButton"..i-4, "RIGHT", 6, 0);
			else
				getglobal("FancyBarButton"..i):SetPoint("TOP", "FancyBarButton"..i-1, "BOTTOM", 0, -6);
			end
		end
	end
end

function FancyBar_ChangeSideBar()
	SideBar_On = 1;
	CenterBar_On = 0;
	CenterBar2_On = 0;
	FancyBarDragButton:Hide();
	FancyBarButton1:ClearAllPoints();
	FancyBarButton1:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", 4, -FancyBar_SideBar_VerticalOffset);

	for i = 2, 12 do
		getglobal("FancyBarButton"..i):ClearAllPoints();
		getglobal("FancyBarButton"..i):SetPoint("TOP", "FancyBarButton"..i-1, "BOTTOM", 0, -6);
	end

	PartyMemberFrame1:ClearAllPoints();
	PartyMemberFrame1:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", 42, -128);
end

function FancyBar_ChangeCenterBar()
	CenterBar_On = 1;
	CenterBar2_On = 0;
	SideBar_On = 0;
	FancyBarButton1:ClearAllPoints();
	FancyBarButton7:ClearAllPoints();
	FancyBarButton1:SetPoint("RIGHT", "FancyBarDragButton", "LEFT", -FancyBar_Center_HorizonOffset, 0);
	FancyBarButton7:SetPoint("LEFT", "FancyBarDragButton", "RIGHT", FancyBar_Center_HorizonOffset, 0);

	for i = 2, 3 do
		getglobal("FancyBarButton"..i):ClearAllPoints();
		getglobal("FancyBarButton"..i):SetPoint("TOP", "FancyBarButton"..i-1, "BOTTOMLEFT", 0, -6);
	end
	FancyBarButton4:ClearAllPoints();
	FancyBarButton4:SetPoint("TOP", "FancyBarButton3", "BOTTOM", 0, -6);
	for i = 5, 6 do
		getglobal("FancyBarButton"..i):ClearAllPoints();
		getglobal("FancyBarButton"..i):SetPoint("TOP", "FancyBarButton"..i-1, "BOTTOMRIGHT", 0, -6);
	end

	for i = 8, 9 do
		getglobal("FancyBarButton"..i):ClearAllPoints();
		getglobal("FancyBarButton"..i):SetPoint("TOP", "FancyBarButton"..i-1, "BOTTOMRIGHT", 0, -6);
	end
	FancyBarButton10:ClearAllPoints();
	FancyBarButton10:SetPoint("TOP", "FancyBarButton9", "BOTTOM", 0, -6);
	for i = 11, 12 do
		getglobal("FancyBarButton"..i):ClearAllPoints();
		getglobal("FancyBarButton"..i):SetPoint("TOP", "FancyBarButton"..i-1, "BOTTOMLEFT", 0, -6);
	end
end

function FancyBar_ChangeCenterBar2()
	CenterBar2_On = 1;
	CenterBar_On = 0;
	SideBar_On = 0;
	FancyBarButton1:ClearAllPoints();
	FancyBarButton7:ClearAllPoints();
	FancyBarButton1:SetPoint("RIGHT", "FancyBarDragButton", "LEFT", -FancyBar_Center_HorizonOffset, 0);
	FancyBarButton7:SetPoint("LEFT", "FancyBarDragButton", "RIGHT", FancyBar_Center_HorizonOffset, 0);

	for i = 2, 6 do
		if ( i == 4 ) then
			FancyBarButton4:ClearAllPoints();
			FancyBarButton4:SetPoint("RIGHT", "FancyBarButton1", "LEFT", -6, 0);
		else
			getglobal("FancyBarButton"..i):ClearAllPoints();
			getglobal("FancyBarButton"..i):SetPoint("TOP", "FancyBarButton"..i-1, "BOTTOM", 0, -6);
		end
	end

	for i = 8, 12 do
		if ( i == 10 ) then
			FancyBarButton10:ClearAllPoints();
			FancyBarButton10:SetPoint("LEFT", "FancyBarButton7", "RIGHT", 6, 0);
		else
			getglobal("FancyBarButton"..i):ClearAllPoints();
			getglobal("FancyBarButton"..i):SetPoint("TOP", "FancyBarButton"..i-1, "BOTTOM", 0, -6);
		end
	end
end

function FancyBar_ChangeFancyBar()
	CenterBar_On = 0;
	CenterBar2_On = 0;
	SideBar_On = 0;
	FancyBar_SetupBar(FancyBar_Vertical, FancyBar_Row);
end

function FancyBar_Center_UpdateOffset(toggle, offset)
	if ( CenterBar_On ~= 1 and CenterBar2_On ~= 1 ) then
		return;
	end
	FancyBar_Center_HorizonOffset = offset;
	FancyBarButton1:SetPoint("RIGHT", "FancyBarDragButton", "LEFT", -FancyBar_Center_HorizonOffset, 0);
	FancyBarButton7:SetPoint("LEFT", "FancyBarDragButton", "RIGHT", FancyBar_Center_HorizonOffset, 0);
end

function FancyBar_SideBar_UpdateOffset(toggle, offset)
	if ( SideBar_On ~= 1 ) then
		return;
	end
	FancyBar_SideBar_VerticalOffset = offset;
	FancyBarButton1:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", 4, -FancyBar_SideBar_VerticalOffset);
end

function FancyBar_SetHideEmpty(toggle)
	if (toggle and (toggle == 1)) then
		if (FancyBar_HideEmpty ~= 1) then
			FancyBar_HideEmpty = 1;
			FancyBarButton_UpdateHidingEmptySlots();
		end
	else
		if (FancyBar_HideEmpty ~= 0) then
			FancyBar_HideEmpty = 0;
			FancyBarButton_UpdateHidingEmptySlots();
		end
	end
end

function FancyBarButton_UpdateHidingEmptySlots()
	local i = 0;
	local name = "FancyBarButton%d";
	local button;
	for i = 1, 12 do
		button = getglobal(format(name, i));
		local id;
		if ( druid_or_priest ) then
			id = 84+i;
		else
			id = 108+i;
		end
		if (button) then
			if (FancyBar_HideEmpty == 0) then
				button.showgrid = 1;
			else
				button.showgrid = 0;
			end
			if (( not (HasAction(id))) and (FancyBar_HideEmpty ~= 0)) then
				button:Hide();
			else
				button:Show();
			end
		end
	end
end

function FancyBarButton_OnLoad()
	this.showgrid = 0;
	this.flashing = 0;
	this.flashtime = 0;
	FancyBarButton_Update();
	this:RegisterForDrag("LeftButton", "RightButton");
	this:RegisterForClicks("LeftButtonUp", "RightButtonUp");
	this:RegisterEvent("PLAYER_ENTERING_WORLD");
	this:RegisterEvent("UPDATE_BONUS_ACTIONBAR");
	this:RegisterEvent("ACTIONBAR_SHOWGRID");
	this:RegisterEvent("ACTIONBAR_HIDEGRID");
	this:RegisterEvent("ACTIONBAR_SLOT_CHANGED");
	this:RegisterEvent("UPDATE_BINDINGS");
	FancyBarButton_UpdateHotkeys("FANCYBARACTIONBUTTON");
end

function FancyBarButton_UpdateHotkeys(actionButtonType)
	if ( not actionButtonType ) then
		actionButtonType = "FANCYBARACTIONBUTTON";
	end
	local hotkey = getglobal(this:GetName().."HotKey");
	local button = FancyBarButton_GetPagedID(this);
	local buttonid, _ = string.gsub(this:GetName(), "FancyBarButton(%d+)", "%1");
	buttonid = tonumber(buttonid);

	if (FancyBar_HideKeys==1) then
		hotkey:SetText(RANGE_INDICATOR);
		hotkey:SetPoint("TOPLEFT", this, "TOPLEFT", 1, -2);
		hotkey:Hide();
	else
		if ((buttonid >= 1) and (buttonid <= 12)) then
			local keyText = GetBindingText(GetBindingKey(actionButtonType..buttonid), "KEY_", 1);
			if (FancyBar_HideKeyMod==1) then
				while ( ( keyText ) and ( strlen(keyText) > 1 ) and (string.find(keyText, "-")) and (keyText ~= "KP -") and (keyText ~= "Num Pad -")) do
					firsti, lasti, keyText = string.find (keyText, "-(.+)");
				end
			end
			if ( ( not keyText ) or ( strlen(keyText) <= 0 ) ) then keyText = ""; end
			if ( keyText == "" ) then
				hotkey:SetText(RANGE_INDICATOR);
				hotkey:SetPoint("TOPLEFT", this, "TOPLEFT", 1, -2);
				hotkey:Hide();
			else
				hotkey:SetText(keyText);
				hotkey:SetPoint("TOPLEFT", this, "TOPLEFT", -2, -2);
				hotkey:Show();
			end
		end
	end
end

function FancyBarButton_Update()
	local action = FancyBarButton_GetPagedID(this);
	local icon = getglobal(this:GetName().."Icon");
	local buttonCooldown = getglobal(this:GetName().."Cooldown");
	local texture = GetActionTexture(action);
	if ( texture ) then
		icon:SetTexture(texture);
		icon:Show();
		this.rangeTimer = TOOLTIP_UPDATE_TIME;
		this:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2");
	else
		icon:Hide();
		buttonCooldown:Hide();
		this.rangeTimer = nil;
		this:SetNormalTexture("Interface\\Buttons\\UI-Quickslot");
		local hotkey = getglobal(this:GetName().."HotKey");
	        if ( hotkey:GetText() == RANGE_INDICATOR ) then
			hotkey:Hide();
		else
			hotkey:SetVertexColor(0.6, 0.6, 0.6);
		end
	end
	FancyBarButton_UpdateCount(this);
	if ( HasAction(action) ) then
		this:RegisterEvent("ACTIONBAR_UPDATE_STATE");
		this:RegisterEvent("ACTIONBAR_UPDATE_USABLE");
		this:RegisterEvent("ACTIONBAR_UPDATE_COOLDOWN");
		this:RegisterEvent("PLAYER_AURAS_CHANGED");
		this:RegisterEvent("PLAYER_TARGET_CHANGED");
		this:RegisterEvent("UNIT_INVENTORY_CHANGED");
		this:RegisterEvent("CRAFT_SHOW");
		this:RegisterEvent("CRAFT_CLOSE");
		this:RegisterEvent("TRADE_SKILL_SHOW");
		this:RegisterEvent("TRADE_SKILL_CLOSE");
		this:RegisterEvent("PLAYER_ENTER_COMBAT");
		this:RegisterEvent("PLAYER_LEAVE_COMBAT");
		this:RegisterEvent("START_AUTOREPEAT_SPELL");
		this:RegisterEvent("STOP_AUTOREPEAT_SPELL");

		this:Show();
		FancyBarButton_UpdateState();
		FancyBarButton_UpdateUsable();
		FancyBarButton_UpdateCooldown(this);
		FancyBarButton_UpdateFlash(this);
	elseif ( (FancyBar_HideEmpty == 1) and (this.showgrid == 0) ) then
		this:Hide();
	else
		this:UnregisterEvent("ACTIONBAR_UPDATE_STATE");
		this:UnregisterEvent("ACTIONBAR_UPDATE_USABLE");
		this:UnregisterEvent("ACTIONBAR_UPDATE_COOLDOWN");
		this:UnregisterEvent("UPDATE_INVENTORY_ALERTS");
		this:UnregisterEvent("PLAYER_AURAS_CHANGED");
		this:UnregisterEvent("PLAYER_TARGET_CHANGED");
		this:UnregisterEvent("CRAFT_SHOW");
		this:UnregisterEvent("CRAFT_CLOSE");
		this:UnregisterEvent("TRADE_SKILL_SHOW");
		this:UnregisterEvent("TRADE_SKILL_CLOSE");
		this:UnregisterEvent("PLAYER_ENTER_COMBAT");
		this:UnregisterEvent("PLAYER_LEAVE_COMBAT");
		this:UnregisterEvent("START_AUTOREPEAT_SPELL");
		this:UnregisterEvent("STOP_AUTOREPEAT_SPELL");

		getglobal(this:GetName().."CooldownCount"):SetText("");
		getglobal(this:GetName().."Cooldown"):Hide();
	end

	-- Add a green border if button is an equipped item
	local border = getglobal(this:GetName().."Border");
	if ( IsEquippedAction(action) ) then
		border:SetVertexColor(0, 1.0, 0, 0.35);
		border:Show();
	else
		border:Hide();
	end
		
	-- Update Macro Text
	local macroName = getglobal(this:GetName().."Name");
	if ( not IsConsumableAction(action) and not IsStackableAction(action) ) then
		macroName:SetText(GetActionText(action));
	else
		macroName:SetText("");
	end

	-- Save the action so we don't update in OnUpdate()
	this.action = action;
end

function FancyBarButton_ShowGrid(button)
	if ( not button ) then
		button = this;
	end
	button.showgrid = button.showgrid+1;
	getglobal(button:GetName().."NormalTexture"):SetVertexColor(1.0, 1.0, 1.0, 0.5);

	if ( not button:GetAttribute("statehidden") ) then
		button:Show();
	end
end

function FancyBarButton_HideGrid(button)	
	if ( not button ) then
		button = this;
	end
	button.showgrid = button.showgrid-1;
	if ( button.showgrid == 0 and not HasAction(FancyBarButton_GetPagedID(button)) ) then
		button:Hide();
	end
end

function FancyBarButton_UpdateState(button)
	if ( not button ) then
		button = this;
	end
	local actionID = FancyBarButton_GetPagedID(button);
	if ( IsCurrentAction(actionID) or IsAutoRepeatAction(actionID) ) then
		button:SetChecked(1);
	else
		button:SetChecked(0);
	end
end

function FancyBarButton_UpdateUsable()
	local icon = getglobal(this:GetName().."Icon");
	local normalTexture = getglobal(this:GetName().."NormalTexture");
	local isUsable, notEnoughMana = IsUsableAction(FancyBarButton_GetPagedID(this));

	if ( isUsable ) then
		local inRange = true;
		if ( this.rangeTimer and (IsActionInRange(FancyBarButton_GetPagedID(this)) == 0)) then
			inRange = false;
		end
		if ( inRange ) then
			icon:SetVertexColor(1.0, 1.0, 1.0);
			normalTexture:SetVertexColor(1.0, 1.0, 1.0);
		else
			icon:SetVertexColor(1.0, 0.5, 0.5);
			normalTexture:SetVertexColor(1.0, 0.5, 0.5);
		end
	elseif ( notEnoughMana ) then
		icon:SetVertexColor(0.5, 0.5, 1.0);
		normalTexture:SetVertexColor(0.5, 0.5, 1.0);
	else
		icon:SetVertexColor(0.4, 0.4, 0.4);
		normalTexture:SetVertexColor(1.0, 1.0, 1.0);
	end
end

function FancyBarButton_UpdateCount()
	local text = getglobal(this:GetName().."Count");
	local action = FancyBarButton_GetPagedID(this);
	if ( IsConsumableAction(action) ) then
		text:SetText(GetActionCount(action));
	else
		text:SetText("");
	end
end

function FancyBarButton_StartButtonCooldown(frame, start, duration, enable)
	local cooldownText = getglobal(frame:GetName().."CooldownCount");
	if not frame or not cooldownText then return; end

	if FancyBar_HideCooldown == 0 and ( start > 0 and duration > 3 and enable > 0 ) then
		cooldownText.start = start
		cooldownText.duration = duration
		cooldownText.timeToNextUpdate = 0
		cooldownText.onCooldown = true
	else
		cooldownText:SetText("")
		cooldownText.onCooldown = false;
	end
end

function FancyBarButton_UpdateButtonCooldown(frame, elapsed)
	local cooldownText = getglobal(frame:GetName().."CooldownCount");
	if not frame or not cooldownText then return; end
	if FancyBar_HideCooldown == 1 then
		cooldownText:SetText("");
		cooldownText.onCooldown = false;
		return;
	end
	if ( cooldownText.onCooldown ) then
		if cooldownText.timeToNextUpdate <= 0 then
			local remain = cooldownText.duration - (GetTime() - cooldownText.start);
			if floor(remain + 0.5) > 0 then
				local text, toNextUpdate, scale = FancyBarButton_FormatTime(remain);
				cooldownText:SetFont(STANDARD_TEXT_FONT, 24.5 * scale, "OUTLINE");
				cooldownText:Show();
				cooldownText:SetText(text);
				cooldownText.timeToNextUpdate = toNextUpdate;
			else
				cooldownText:SetText("");
				cooldownText.onCooldown = false;
			end
		else
			cooldownText.timeToNextUpdate = cooldownText.timeToNextUpdate - elapsed;
		end
	end
end

function FancyBarButton_FormatTime(secs)
	if secs > 86400 then
		return floor(secs / 86400 + 0.5) .. FANCYBAR_DAY, mod(secs, 86400), 0.75;
	elseif secs > 3600 then
		return floor(secs / 3600 + 0.5) .. FANCYBAR_HOUR, mod(secs, 3600), 0.75;
	elseif secs > 60 then
		return floor(secs / 60 + 0.5) .. FANCYBAR_MINUTE, mod(secs, 60), 0.75;
	end
	return floor(secs + 0.5), secs - floor(secs), 1;
end

function FancyBarButton_UpdateCooldown()
	local cooldown = getglobal(this:GetName().."Cooldown");
	local start, duration, enable = GetActionCooldown(FancyBarButton_GetPagedID(this));
	CooldownFrame_SetTimer(cooldown, start, duration, enable);
	FancyBarButton_StartButtonCooldown(this, start, duration, enable);
end

function FancyBarButton_OnEvent(event)
	if ( event == "ACTIONBAR_SLOT_CHANGED" ) then
		if ( arg1 == 0 or arg1 == FancyBarButton_GetPagedID(this) ) then
			FancyBarButton_Update();
		end
		return;
	end
	if ( event == "PLAYER_ENTERING_WORLD" ) then
		FancyBarButton_Update();
		return;
	end
	if ( event == "ACTIONBAR_SHOWGRID" ) then
		FancyBarButton_ShowGrid();
		return;
	end
	if ( event == "ACTIONBAR_HIDEGRID" ) then
		FancyBarButton_HideGrid();
		return;
	end
	if ( event == "UPDATE_BINDINGS" ) then
		FancyBarButton_UpdateHotkeys("FANCYBARACTIONBUTTON");
		return;
	end

	-- All event handlers below this line are only set when the button has an action

	if ( event == "PLAYER_TARGET_CHANGED" ) then
		this.rangeTimer = -1;
	elseif ( event == "ACTIONBAR_UPDATE_STATE" ) then
		FancyBarButton_UpdateState();
	elseif ( event == "ACTIONBAR_UPDATE_USABLE" ) then
		FancyBarButton_UpdateUsable();
	elseif ( event == "ACTIONBAR_UPDATE_COOLDOWN" ) then
		FancyBarButton_UpdateCooldown();
	elseif ( event == "CRAFT_SHOW" or event == "CRAFT_CLOSE" or event == "TRADE_SKILL_SHOW" or event == "TRADE_SKILL_CLOSE" ) then
		FancyBarButton_UpdateState();
	elseif ( event == "PLAYER_ENTER_COMBAT" ) then
		if ( IsAttackAction(FancyBarButton_GetPagedID(this)) ) then
			FancyBarButton_StartFlash();
		end
	elseif ( event == "PLAYER_LEAVE_COMBAT" ) then
		if ( IsAttackAction(FancyBarButton_GetPagedID(this)) ) then
			FancyBarButton_StopFlash();
		end
	elseif ( event == "START_AUTOREPEAT_SPELL" ) then
		if ( IsAutoRepeatAction(FancyBarButton_GetPagedID(this)) ) then
			FancyBarButton_StartFlash();
		end
	elseif ( event == "STOP_AUTOREPEAT_SPELL" ) then
		if ( FancyBarButton_IsFlashing() and not IsAttackAction(FancyBarButton_GetPagedID(this)) ) then
			FancyBarButton_StopFlash();
		end
	end
end

function FancyBarButton_SetTooltip(self)
	if ( GetCVar("UberTooltips") == "1" ) then
		GameTooltip_SetDefaultAnchor(GameTooltip, self);
	else
		GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
	end
	
	if ( GameTooltip:SetAction(FancyBarButton_GetPagedID(self)) ) then
		self.UpdateTooltip = FancyBarButton_SetTooltip;
	else
		self.UpdateTooltip = nil;
	end
end

function FancyBarButton_OnUpdate(elapsed)

	local action = FancyBarButton_GetPagedID(this);

	if ( this.action ~= action ) then
		FancyBarButton_Update();
	end

	if ( HasAction(action) ) then
		FancyBarButton_UpdateButtonCooldown(this, elapsed);
	end

	if ( FancyBarButton_IsFlashing() ) then
		this.flashtime = this.flashtime - elapsed;
		if ( this.flashtime <= 0 ) then
			local overtime = -this.flashtime;
			if ( overtime >= ATTACK_BUTTON_FLASH_TIME ) then
				overtime = 0;
			end
			this.flashtime = ATTACK_BUTTON_FLASH_TIME - overtime;

			local flashTexture = getglobal(this:GetName().."Flash");
			if ( flashTexture:IsShown() ) then
				flashTexture:Hide();
			else
				flashTexture:Show();
			end
		end
	end
	
	-- Handle range indicator
	if ( this.rangeTimer ) then
		this.rangeTimer = this.rangeTimer - elapsed;

		if ( this.rangeTimer <= 0 ) then
			FancyBarButton_UpdateUsable();
			local count = getglobal(this:GetName().."HotKey");
			local valid = IsActionInRange(action);
			if ( count:GetText() == RANGE_INDICATOR ) then
				if ( valid == 0 ) then
					count:Show();
					count:SetVertexColor(1.0, 0.1, 0.1);
				elseif ( valid == 1 ) then
					count:Show();
					count:SetVertexColor(0.6, 0.6, 0.6);
				else
					count:Hide();
				end
			else
				if ( valid == 0 ) then
					count:SetVertexColor(1.0, 0.1, 0.1);
				else
					count:SetVertexColor(0.6, 0.6, 0.6);
				end
			end
			this.rangeTimer = TOOLTIP_UPDATE_TIME;
		end
	end
end

function FancyBarButton_GetPagedID(button)
	local buttonid, _ = string.gsub(button:GetName(), "FancyBarButton(%d+)", "%1");
	buttonid = tonumber(buttonid);

	if ( buttonid > 0 ) then
		local prefixid;
		if ( druid_or_priest ) then
			prefixid = 84;
		else
			prefixid = 108;
		end
		return prefixid+buttonid;
	else
		return SecureButton_GetModifiedAttribute(button, "action", SecureStateChild_GetEffectiveButton(button)) or 1;
	end
end

function FancyBarButton_UpdateFlash()
	local action = FancyBarButton_GetPagedID(this);
	if ( (IsAttackAction(action) and IsCurrentAction(action)) or IsAutoRepeatAction(action) ) then
		FancyBarButton_StartFlash();
	else
		FancyBarButton_StopFlash();
	end
end

function FancyBarButton_StartFlash()
	this.flashing = 1;
	this.flashtime = 0;
	FancyBarButton_UpdateState();
end

function FancyBarButton_StopFlash()
	this.flashing = 0;
	getglobal(this:GetName().."Flash"):Hide();
	FancyBarButton_UpdateState();
end

function FancyBarButton_IsFlashing()
	if ( this.flashing == 1 ) then
		return 1;
	else
		return nil;
	end
end