--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
--|	GypsyMod HotBar - Gypsy_SpecialActionBar.lua
--|	Special action bar functions
--|	Special action button functions
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--

--= Libraries =--

local color = Gypsy_Color:New();
local capsule = Gypsy_Capsule:New();
local hotlib = Gypsy_HotLib:New();

-- Load HotLib label filters
hotlib:LoadLabelFilters(HOTBAR_TEXT:Get("labelFilters"));

-- Add custom special action bar grey color to library
color:Add("sab_darkgrey", 0.4);

--= Variables =--

-- Saved variables shortcut table
local saved = nil;

-- Number of buttons
local numButtons = 10;

-- Special action button name prefix
local specialActionPrefix = "Gypsy_SpecialActionButton";

-- Docked data
local dockedData = {
	["HORI"] = {
		["point"] = "BOTTOM";
		["relPoint"] = "TOP";
	};
	["VERT"] = {
		["point"] = "LEFT";
		["relPoint"] = "RIGHT";
	};
};

--= Helper Functions =--

-- Returns a scaling ratio used for determining capsule size
local function getRatio ()
	if (saved.setScale == 1) then
		return hotlib:GetScale(saved.size) / UIParent:GetScale();
	else
		return hotlib:GetScale(saved.specialactionbar_buttonSize) / UIParent:GetScale();
	end
end

-- Quick check to determine whether to use the saved size property
local function getButtonSize ()
	if (saved.setScale == 1) then
		return saved.size;
	else
		return saved.specialactionbar_buttonSize;
	end
end

-- Get width & height convenience functions
local function getWidth (orient)
	return hotlib:GetGroupWidth(orient, GetNumShapeshiftForms(), getButtonSize(), getButtonSize(), saved.gap * getRatio());
end

local function getHeight (orient)
	return hotlib:GetGroupHeight(orient, GetNumShapeshiftForms(), getButtonSize(), getButtonSize(), saved.gap * getRatio());
end

--= Special Action Bar Management Functions =--

function Gypsy_SpecialActionBar_Initialize (player)
	Gypsy_SpecialActionBar_LoadConfig(player);
	
	local args = {};
	args.frame = "Gypsy_SpecialActionBar_Capsule";
	if (saved.enabled == 0 or saved.specialactionbar_enabled == 0) then
		args.enabled = 0;
	end
	args.locked = saved.specialactionbar_locked;
	args.doDir = 0;
	local orient;
	if (saved.specialactionbar_docked == 1) then
		orient = saved.actionbar1_orient;
	else
		orient = saved.specialactionbar_orient;
	end
	args.orient = orient;
	args.initFunc = "Gypsy_SpecialActionBar_Update";
	args.orientFunc = "Gypsy_SpecialActionBar_Update";
	args.ordFunc = "Gypsy_SpecialActionBar_Update";
	args.menuFunc = "Gypsy_SpecialActionBar_DropDown_Toggle";
	args.title = HOTBAR_TEXT:Get("specialactionbar");
	args.tooltipTitle = HOTBAR_TEXT:Get("specialactionbar");
	args.tooltipText = HOTBAR_TEXT:Get("capsuleTooltip");
	args.ratio = getRatio();
	args.width = getWidth(saved.specialactionbar_orient);
	args.height = getHeight(saved.specialactionbar_orient);
	capsule:Register(args);
	
	UIDropDownMenu_Initialize(Gypsy_SpecialActionBar_DropDown, Gypsy_SpecialActionBar_UpdateDropDown, "MENU");
end

function Gypsy_SpecialActionBar_LoadConfig (player)
	saved = GYPSY_SAVED_HOTBAR[player];
end

function Gypsy_SpecialActionBar_ValidateSettings ()
	if (saved.actionbar1_shown == 0) then
		saved.specialactionbar_docked = 0;
	end
end

function Gypsy_SpecialActionBar_Update ()
	if (saved.enabled == 1 and saved.specialactionbar_shown == 1) then
		local orient;
		local size = getButtonSize();
		
		if (saved.specialactionbar_docked == 1 and saved.actionbar1_shown == 1) then
			if (not Gypsy_ActionBar1_Capsule.initialized) then
				return;
			end
			
			orient = saved.actionbar1_orient;
			capsule:Disable(Gypsy_SpecialActionBar_Capsule);
			
			local x = 0;
			local y = 0;
			
			if (orient == "HORI") then
				if (strfind(Gypsy_ActionBar1_Capsule.quadrant, "TOP")) then
					y = -saved.gap;
				else
					y = saved.gap;
				end
			else
				if (strfind(Gypsy_ActionBar1_Capsule.quadrant, "LEFT")) then
					x = saved.gap;
				else
					x = -saved.gap;
				end
			end
			
			local rel = nil;
			
			for i=6, 2, -1 do
				if (saved["actionbar"..i.."_docked"] == 1 and saved["actionbar"..i.."_shown"] == 1) then
					rel = "Gypsy_ActionButton"..(12 * (i - 1)) + 2;
					break;
				end
			end
			
			if (not rel) then
				rel = "Gypsy_ActionButton2";
			end
			
			local point, relPoint;
			
			if (orient == "HORI") then
				if (strfind(Gypsy_ActionBar1_Capsule.quadrant, "TOP")) then
					point = dockedData[orient].relPoint;
					relPoint = dockedData[orient].point;
				else
					point = dockedData[orient].point;
					relPoint = dockedData[orient].relPoint;
				end
			else
				if (strfind(Gypsy_ActionBar1_Capsule.quadrant, "LEFT")) then
					point = dockedData[orient].point;
					relPoint = dockedData[orient].relPoint;
				else
					point = dockedData[orient].relPoint;
					relPoint = dockedData[orient].point;
				end
			end
			
			Gypsy_SpecialActionButton1:ClearAllPoints();
			Gypsy_SpecialActionButton1:SetPoint(point, rel, relPoint, x, y);
		else
			orient = saved.specialactionbar_orient;
			capsule:Enable(Gypsy_SpecialActionBar_Capsule);
			
			if (not Gypsy_SpecialActionBar_Capsule:IsUserPlaced()) then
				Gypsy_SpecialActionBar_Capsule:ClearAllPoints();
				Gypsy_SpecialActionBar_Capsule:SetPoint("BOTTOM", "UIParent", "BOTTOM", 0, 350);
			end
			
			Gypsy_SpecialActionButton1:ClearAllPoints();
			Gypsy_SpecialActionButton1:SetPoint("TOPLEFT", "Gypsy_SpecialActionBar_Capsule", "TOPLEFT", capsule.padding, -capsule.padding);
		end
		
		hotlib:ShowButton(Gypsy_SpecialActionButton1);
		
		for i=2, numButtons do
			hotlib:ShowButton(getglobal(specialActionPrefix..i), orient, saved.gap, specialActionPrefix..i - 1);
		end
		
		Gypsy_SpecialActionBar_Scale();
		
		if (Gypsy_SpecialActionBar_Capsule.initialized and Gypsy_SpecialActionBar_Capsule.enabled == 1) then
			Gypsy_SpecialActionBar_Capsule.ratio = getRatio();
			Gypsy_SpecialActionBar_Capsule.width = getWidth(orient);
			Gypsy_SpecialActionBar_Capsule.height = getHeight(orient);
			capsule:Size(Gypsy_SpecialActionBar_Capsule);
			if (Gypsy_SpecialActionBar_Capsule.orient ~= orient) then
				capsule:UpdateOrientation(Gypsy_SpecialActionBar_Capsule, orient);
			end
		end
	else
		hotlib:HideGroup(specialActionPrefix, 1, numButtons);
		capsule:Disable(Gypsy_SpecialActionBar_Capsule);
	end
	Gypsy_SpecialActionBar_UpdateState();
	Gypsy_SpecialActionBar_UpdateBindings();
end

function Gypsy_SpecialActionBar_Scale ()
	local size = getButtonSize();
	
	for i=1, numButtons do
		hotlib:ScaleButton(getglobal(specialActionPrefix..i), size);
	end
end


function Gypsy_SpecialActionBar_Reset ()
	Gypsy_SpecialActionBar_Capsule:SetUserPlaced(0);
end

--= DropDown Functions =--

function Gypsy_SpecialActionBar_DropDown_OnShow ()
	UIDropDownMenu_Initialize(this, Gypsy_SpecialActionBar_UpdateDropDown, "MENU");
end

function Gypsy_SpecialActionBar_DropDown_Toggle ()
	hotlib:ToggleDropDown("Gypsy_SpecialActionBar");
end

function Gypsy_SpecialActionBar_LoadMenu (level)
	local info = {};
	info.text = HOTBAR_TEXT:Get("show");
	if (saved.specialactionbar_shown == 1) then
		info.checked = 1;
	end
	info.func = function ()
		if (this.checked) then
			saved.specialactionbar_shown = 0;
		else
			saved.specialactionbar_shown = 1;
		end
		Gypsy_SpecialActionBar_ValidateSettings();
		Gypsy_SpecialActionBar_Update();
		Gypsy_ActionBar_Update();
	end
	UIDropDownMenu_AddButton(info, level);
	info = {};
	info.text = HOTBAR_TEXT:Get("docked");
	if (saved.specialactionbar_docked == 1 and saved.actionbar1_shown == 1) then
		info.checked = 1;
	end
	info.func = function ()
		if (this.checked) then
			saved.specialactionbar_docked = 0;
		else
			saved.specialactionbar_docked = 1;
		end
		Gypsy_SpecialActionBar_ValidateSettings();
		Gypsy_SpecialActionBar_Update();
		Gypsy_ActionBar_Update();
	end
	if (saved.actionbar1_shown == 0 or saved.specialactionbar_shown == 0) then
		info.disabled = 1;
	end
	UIDropDownMenu_AddButton(info, level);
	info = {};
	info.text = HOTBAR_TEXT:Get("orientation");
	info.hasArrow = 1;
	info.notCheckable = 1;
	info.value = "specialactionbar_orientation";
	if (saved.specialactionbar_shown == 0 or saved.specialactionbar_docked == 1) then
		info.disabled = 1;
	end
	UIDropDownMenu_AddButton(info, level);
	info = {};
	info.text = HOTBAR_TEXT:Get("buttonSize");
	info.hasArrow = 1;
	info.notCheckable = 1;
	info.value = "specialactionbar_buttonsize";
	if (saved.specialactionbar_shown == 0) then
		info.disabled = 1;
	end
	UIDropDownMenu_AddButton(info, level);
end

function Gypsy_SpecialActionBar_UpdateDropDown ()
	local info = {};
	
	if (UIDROPDOWNMENU_MENU_LEVEL == 2) then
		if (strfind(UIDROPDOWNMENU_MENU_VALUE, "orientation")) then
			info = {};
			info.text = HOTBAR_TEXT:Get("horizontal");
			if (saved.specialactionbar_orient == "HORI") then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.specialactionbar_orient = "HORI";
					capsule:UpdateOrientation(Gypsy_SpecialActionBar_Capsule, "HORI");
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = HOTBAR_TEXT:Get("vertical");
			if (saved.specialactionbar_orient == "VERT") then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.specialactionbar_orient = "VERT";
					capsule:UpdateOrientation(Gypsy_SpecialActionBar_Capsule, "VERT");
				end
			end
			UIDropDownMenu_AddButton(info, 2);
		else
			info = {};
			info.text = "18"..HOTBAR_TEXT:Get("px");
			if (saved.specialactionbar_buttonSize == 18) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.specialactionbar_buttonSize = 18;
					if (saved.specialactionbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_SpecialActionBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = "24"..HOTBAR_TEXT:Get("px");
			if (saved.specialactionbar_buttonSize == 24) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.specialactionbar_buttonSize = 24;
					if (saved.specialactionbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_SpecialActionBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = "30"..HOTBAR_TEXT:Get("px");
			if (saved.specialactionbar_buttonSize == 30) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.specialactionbar_buttonSize = 30;
					if (saved.specialactionbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_SpecialActionBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = "36"..HOTBAR_TEXT:Get("px");
			if (saved.specialactionbar_buttonSize == 36) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.specialactionbar_buttonSize = 36;
					if (saved.specialactionbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_SpecialActionBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = "42"..HOTBAR_TEXT:Get("px");
			if (saved.specialactionbar_buttonSize == 42) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.specialactionbar_buttonSize = 42;
					if (saved.specialactionbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_SpecialActionBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = "48"..HOTBAR_TEXT:Get("px");
			if (saved.specialactionbar_buttonSize == 48) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.specialactionbar_buttonSize = 48;
					if (saved.specialactionbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_SpecialActionBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);	
		end
		
		return;
	end
	
	info = {};
	info.text = HOTBAR_TEXT:Get("specialactionbar");
	info.isTitle = 1;
	info.notCheckable = 1;
	UIDropDownMenu_AddButton(info);
	Gypsy_SpecialActionBar_LoadMenu();
end

--= Special Action Bar Functions =--

function Gypsy_SpecialActionBar_OnLoad ()
	this:RegisterEvent("UPDATE_SHAPESHIFT_FORMS");
	this:RegisterEvent("ACTIONBAR_UPDATE_USABLE");
	this:RegisterEvent("UPDATE_INVENTORY_ALERTS");
	this:RegisterEvent("SPELL_UPDATE_COOLDOWN");
	this:RegisterEvent("SPELL_UPDATE_USABLE");
	this:RegisterEvent("PLAYER_AURAS_CHANGED");
	this:RegisterEvent("UNIT_HEALTH");
	this:RegisterEvent("UNIT_HEALTH");
	this:RegisterEvent("UNIT_RAGE");
	this:RegisterEvent("UNIT_FOCUS");
	this:RegisterEvent("UNIT_ENERGY");
	this:RegisterEvent("UPDATE_BINDINGS");
	Gypsy_SpecialActionBar_UpdateState();
end

function Gypsy_SpecialActionBar_OnEvent (event)
	if (event == "UPDATE_BINDINGS") then
		Gypsy_SpecialActionBar_UpdateBindings();
		return;
	end
	Gypsy_SpecialActionBar_UpdateState();
end

function Gypsy_SpecialActionBar_UpdateState ()
	local numForms = GetNumShapeshiftForms();
	local name, isActive, isCastable;
	local button, icon, cooldown;
	local start, duration, enable;
	
	for i=1, numButtons do
		button = getglobal("Gypsy_SpecialActionButton"..i);
		icon = getglobal("Gypsy_SpecialActionButton"..i.."Icon");
		if (i <= numForms and saved and saved.enabled == 1 and saved.specialactionbar_shown == 1) then
			texture, name, isActive, isCastable = GetShapeshiftFormInfo(i);
			icon:SetTexture(texture);
			
			cooldown = getglobal(button:GetName().."Cooldown");
			if (texture) then
				cooldown:Show();
			else
				cooldown:Hide();
			end
			start, duration, enable = GetShapeshiftFormCooldown(i);
			CooldownFrame_SetTimer(cooldown, start, duration, enable);
			
			if (isActive) then
				Gypsy_SpecialActionBar.lastSelected = button:GetID();
				button:SetChecked(1);
			else
				button:SetChecked(0);
			end
			
			if (isCastable) then
				icon:SetVertexColor(color:Parse("white"));
			else
				icon:SetVertexColor(color:Parse("sab_darkgrey"));
			end
			
			button:Show();
		else
			button:Hide();
		end
	end
end

function Gypsy_SpecialActionBar_UpdateBindings ()
	local label, binding;
	
	for i=1, numButtons do
		label = getglobal("Gypsy_SpecialActionButton"..i.."HotKey");
		if (saved and saved.bindingLabelMode == "id" and saved.showSpecialActionLabels == 1) then
			label:SetText(i);
		elseif (saved and saved.bindingLabelMode ~= "hidden" and saved.showSpecialActionLabels == 1) then
			binding = GetBindingText(GetBindingKey("SHAPESHIFTBUTTON"..i), "KEY_");
			binding = hotlib:CondenseLabel(binding);
			
			if (saved.bindingLabelMode == "stripped") then
				binding = hotlib:StripCondensedLabel(binding);
			end
			
			label:SetText(binding);
		else
			label:SetText("");
		end
	end
end

function Gypsy_SpecialActionBar_ChangeForm (id)
	Gypsy_SpecialActionBar.lastSelected = id;
	CastShapeshiftForm(id);
end

--= Special Action Button Functions =--

function Gypsy_SpecialActionButton_OnClick ()
	if (this:GetChecked()) then
		this:SetChecked(0);
	else
		this:SetChecked(1);
	end
	Gypsy_SpecialActionBar_ChangeForm(this:GetID());
end

function Gypsy_SpecialActionButton_OnEnter ()
	if (GetCVar("UberTooltips") == "1") then
		GameTooltip_SetDefaultAnchor(GameTooltip, this);
	else
		GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
	end
	GameTooltip:SetShapeshift(this:GetID());
end

function Gypsy_SpecialActionButton_OnLeave ()
	if (GameTooltip:IsOwned(this)) then
		GameTooltip:Hide();
	end
end