--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
--|	GypsyMod HotBar - Gypsy_PetActionBar.lua
--|	PetActionBar functions
--|	PetActionButton 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"));

--= Variables =--

-- Saved variable shortcut table
local saved = nil;

-- Number of pet action buttons
local numButtons = 10;

-- Button name prefix
local petActionPrefix = "Gypsy_PetActionButton";

-- 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.petactionbar_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.petactionbar_buttonSize;
	end
end

-- Manual application of hotkeys to all buttons
local function updateHotkeys ()
	for i=1, numButtons do
		Gypsy_PetActionButton_SetHotkeys(getglobal(petActionPrefix..i));
	end
end

--= Pet Action Bar Management Functions =--

function Gypsy_PetActionBar_Initialize (player)
	Gypsy_PetActionBar_LoadConfig(player);
	
	Gypsy_PetActionBar.showgrid = saved.showPlaceholders;
	
	local args = {};
	args.frame = "Gypsy_PetActionBar_Capsule";
	if (saved.enabled == 0 or saved.petactionbar_shown == 0) then
		args.enabled = 0;
	end
	args.locked = saved.petactionbar_locked;
	args.doDir = 0;
	local orient;
	if (saved.petactionbar_docked == 1) then
		orient = saved.actionbar1_orient;
	else
		orient = saved.petactionbar_orient;
	end
	args.orient = orient;
	args.initFunc = "Gypsy_PetActionBar_Update";
	args.orientFunc = "Gypsy_PetActionBar_Update";
	args.ordFunc = "Gypsy_PetActionBar_Update";
	args.menuFunc = "Gypsy_PetActionBar_DropDown_Toggle";
	args.title = HOTBAR_TEXT:Get("petactionbar");
	args.tooltipTitle = HOTBAR_TEXT:Get("petactionbar");
	args.tooltipText = HOTBAR_TEXT:Get("capsuleTooltip");
	args.ratio = getRatio();
	args.width = hotlib:GetGroupWidth(orient, numButtons, getButtonSize(), getButtonSize(), saved.gap * getRatio());
	args.height = hotlib:GetGroupHeight(orient, numButtons, getButtonSize(), getButtonSize(), saved.gap * getRatio());
	capsule:Register(args);
	
	UIDropDownMenu_Initialize(Gypsy_PetActionBar_DropDown, Gypsy_PetActionBar_UpdateDropDown, "MENU");
end

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

function Gypsy_PetActionBar_ValidateSettings ()
	if (saved.actionbar1_shown == 0) then
		saved.petactionbar_docked = 0;
	end
end

function Gypsy_PetActionBar_Update (noCall)
	if (saved.enabled == 1 and saved.petactionbar_shown == 1) then
		local orient;
		
		local size = getButtonSize();
		
		if (saved.petactionbar_docked == 1 and saved.actionbar1_shown == 1) then
			orient = saved.actionbar1_orient;
			capsule:Disable(Gypsy_PetActionBar_Capsule);
			
			local x = 0;
			local y = 0;			

			--if (Gypsy_ActionBar1_Capsule.quadrant) then
				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
						y = -saved.gap;
					end
				end
			--else
			--	y = saved.gap;
			--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_PetActionButton1:ClearAllPoints();
			Gypsy_PetActionButton1:SetPoint(point, rel, relPoint, x, y);
		else
			orient = saved.petactionbar_orient;
			capsule:Enable(Gypsy_PetActionBar_Capsule);

			if (not Gypsy_PetActionBar_Capsule:IsUserPlaced()) then
				Gypsy_PetActionBar_Capsule:ClearAllPoints();
				Gypsy_PetActionBar_Capsule:SetPoint("BOTTOM", "UIParent", "BOTTOM", 0, 350);
			end
			
			Gypsy_PetActionButton1:ClearAllPoints();
			Gypsy_PetActionButton1:SetPoint("TOPLEFT", "Gypsy_PetActionBar_Capsule", "TOPLEFT", capsule.padding, -capsule.padding);
		end
		
		--hotlib:ShowButton(Gypsy_PetActionButton1);
		
		for i=2, numButtons do
			hotlib:PlaceButton(getglobal(petActionPrefix..i), orient, saved.gap, petActionPrefix..i - 1);
		end
		
		Gypsy_PetActionBar_Scale();
		
		if (Gypsy_PetActionBar_Capsule.initialized and Gypsy_PetActionBar_Capsule.enabled == 1) then
			local ratio = getRatio();
			Gypsy_PetActionBar_Capsule.ratio = ratio;
			Gypsy_PetActionBar_Capsule.width = hotlib:GetGroupWidth(orient, numButtons, size, size, saved.gap * ratio);
			Gypsy_PetActionBar_Capsule.height = hotlib:GetGroupHeight(orient, numButtons, size, size, saved.gap * ratio);
			capsule:Size(Gypsy_PetActionBar_Capsule);
			if (Gypsy_PetActionBar_Capsule.orient ~= orient) then
				capsule:UpdateOrientation(Gypsy_PetActionBar_Capsule, orient);
			end
		end
		updateHotkeys();
	else
		--hotlib:HideGroup(petActionPrefix, 1, numButtons);
		capsule:Disable(Gypsy_PetActionBar_Capsule);
	end
	
	if (not noCall) then
		Gypsy_PetActionBar_UpdateState(1);
	end
	
	Gypsy_ActionBar1_UpdateSize();
end

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

function Gypsy_PetActionBar_Reset ()
	Gypsy_PetActionBar_Capsule:SetUserPlaced(0);
end

--= DropDown Functions =--

function Gypsy_PetActionBar_DropDown_OnShow ()
	UIDropDownMenu_Initialize(this, Gypsy_PetActionBar_UpdateDropDown, "MENU");
end

function Gypsy_PetActionBar_DropDown_Toggle ()
	hotlib:ToggleDropDown("Gypsy_PetActionBar");
end

function Gypsy_PetActionBar_LoadMenu (level)
	local info = {};
	info.text = HOTBAR_TEXT:Get("show");
	if (saved.petactionbar_shown == 1) then
		info.checked = 1;
	end
	info.func = function ()
		if (this.checked) then
			saved.petactionbar_shown = 0;
		else
			saved.petactionbar_shown = 1;
		end
		Gypsy_PetActionBar_ValidateSettings();
		Gypsy_PetActionBar_Update();
	end
	UIDropDownMenu_AddButton(info, level);
	info = {};
	info.text = HOTBAR_TEXT:Get("docked");
	if (saved.petactionbar_docked == 1 and saved.actionbar1_shown == 1) then
		info.checked = 1;
	end
	info.func = function ()
		if (this.checked) then
			saved.petactionbar_docked = 0;
			Gypsy_PetActionBar_ValidateSettings();
			Gypsy_PetActionBar_Update();
			Gypsy_ActionBar1_Update();
		else
			saved.petactionbar_docked = 1;
			Gypsy_PetActionBar_ValidateSettings();
			Gypsy_ActionBar1_Update();
		end
	end
	if (saved.actionbar1_shown == 0 or saved.petactionbar_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 = "petactionbar_orientation";
	if (saved.petactionbar_shown == 0 or saved.petactionbar_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 = "petactionbar_buttonsize";
	if (saved.petactionbar_shown == 0) then
		info.disabled = 1;
	end
	UIDropDownMenu_AddButton(info, level);
end

function Gypsy_PetActionBar_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.petactionbar_orient == "HORI") then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.petactionbar_orient = "HORI";
					capsule:UpdateOrientation(Gypsy_PetActionBar_Capsule, "HORI");
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = HOTBAR_TEXT:Get("vertical");
			if (saved.petactionbar_orient == "VERT") then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.petactionbar_orient = "VERT";
					capsule:UpdateOrientation(Gypsy_PetActionBar_Capsule, "VERT");
				end
			end
			UIDropDownMenu_AddButton(info, 2);
		else
			info = {};
			info.text = "18"..HOTBAR_TEXT:Get("px");
			if (saved.petactionbar_buttonSize == 18) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.petactionbar_buttonSize = 18;
					if (saved.petactionbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_PetActionBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = "24"..HOTBAR_TEXT:Get("px");
			if (saved.petactionbar_buttonSize == 24) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.petactionbar_buttonSize = 24;
					if (saved.petactionbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_PetActionBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = "30"..HOTBAR_TEXT:Get("px");
			if (saved.petactionbar_buttonSize == 30) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.petactionbar_buttonSize = 30;
					if (saved.petactionbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_PetActionBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = "36"..HOTBAR_TEXT:Get("px");
			if (saved.petactionbar_buttonSize == 36) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.petactionbar_buttonSize = 36;
					if (saved.petactionbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_PetActionBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = "42"..HOTBAR_TEXT:Get("px");
			if (saved.petactionbar_buttonSize == 42) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.petactionbar_buttonSize = 42;
					if (saved.petactionbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_PetActionBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = "48"..HOTBAR_TEXT:Get("px");
			if (saved.petactionbar_buttonSize == 48) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.petactionbar_buttonSize = 48;
					if (saved.petactionbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_PetActionBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);	
		end
		
		return;
	end
	
	info = {};
	info.text = HOTBAR_TEXT:Get("petactionbar");
	info.isTitle = 1;
	info.notCheckable = 1;
	UIDropDownMenu_AddButton(info);
	Gypsy_PetActionBar_LoadMenu();
end

--= Pet Action Bar Functions =--

function Gypsy_PetActionBar_OnLoad ()
	this:RegisterEvent("PLAYER_CONTROL_LOST");
	this:RegisterEvent("PLAYER_CONTROL_GAINED");
	this:RegisterEvent("PLAYER_FARSIGHT_FOCUS_CHANGED");
	this:RegisterEvent("UNIT_PET");
	this:RegisterEvent("UNIT_FLAGS");
	this:RegisterEvent("UNIT_AURA");
	this:RegisterEvent("PET_BAR_UPDATE");
	this:RegisterEvent("PET_BAR_UPDATE_COOLDOWN");
	this:RegisterEvent("PET_BAR_SHOWGRID");
	this:RegisterEvent("PET_BAR_HIDEGRID");
	
	this.showgrid = 0;
	
	Gypsy_PetActionBar_UpdateState();
end

function Gypsy_PetActionBar_OnEvent (event)
	if (event == "PLAYER_CONTROL_LOST" or event == "PLAYER_CONTROL_GAINED" or event == "PLAYER_FARSIGHT_FOCUS_CHANGED") then
		Gypsy_PetActionBar_UpdateState(1);
		return;
	end
	if (arg1 == "pet" and (event == "UNIT_FLAGS" or event == "UNIT_AURA")) then
		Gypsy_PetActionBar_UpdateState(1);
		return;
	end
	if (event == "PET_BAR_UPDATE"or (event == "UNIT_PET" and arg1 == "player")) then
		Gypsy_PetActionBar_UpdateState();
		return;
	end
	if (event == "PET_BAR_UPDATE_COOLDOWN") then
		Gypsy_PetActionBar_UpdateCooldowns();
		return;
	end
	if (event == "PET_BAR_SHOWGRID") then
		Gypsy_PetActionBar_ShowGrid();
		return;
	end
	if (event == "PET_BAR_HIDEGRID") then
		Gypsy_PetActionBar_HideGrid();
		return;
	end
end

function Gypsy_PetActionBar_UpdateState (noCall)
	local button, icon, autoCastableTexture, autoCastModel;
	local petActionsUsable = GetPetActionsUsable();

	for i=1, numButtons do
		button = getglobal("Gypsy_PetActionButton"..i);
		icon = getglobal(button:GetName().."Icon");
		autoCastableTexture = getglobal(button:GetName().."AutoCastable");
		autoCastModel = getglobal(button:GetName().."AutoCast");

		local name, subtext, texture, isToken, isActive, autoCastAllowed, autoCastEnabled = GetPetActionInfo(i);

		if (not isToken) then
			icon:SetTexture(texture);
			button.tooltipName = name;
		else
			icon:SetTexture(getglobal(texture));
			button.tooltipName = TEXT(getglobal(name));
		end

		button.isToken = isToken;
		button.tooltipSubtext = subtext;

		if (isActive) then
			button:SetChecked(1);
		else
			button:SetChecked(0);
		end

		if (autoCastAllowed) then
			autoCastableTexture:Show();
		else
			autoCastableTexture:Hide();
		end

		if (autoCastEnabled) then
			autoCastModel:Show();
		else
			autoCastModel:Hide();
		end

		if (not PetHasActionBar() or not saved or saved.enabled == 0 or saved.petactionbar_shown == 0) then
			button:Hide();
			icon:Hide();
		else
			if (name) then
				button:Show();
			else
				if (Gypsy_PetActionBar.showgrid == 0) then
					button:Hide();
				else
					button:Show();
				end
			end

			if (texture) then
				if (petActionsUsable) then
					SetDesaturation(icon, nil);
				else
					SetDesaturation(icon, 1);
				end
				icon:Show();
				button:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2");
			else
				icon:Hide();
				button:SetNormalTexture("Interface\\Buttons\\UI-Quickslot");
			end
		end
	end
	Gypsy_PetActionBar_UpdateCooldowns();
	
	if (saved and not noCall) then
		if (saved.petactionbar_docked == 1) then
			if (not Gypsy_ActionBar1_Capsule.quadrant) then
				return;
			end
		end
		
		Gypsy_PetActionBar_Update(1);
	end
end

function Gypsy_PetActionBar_UpdateCooldowns ()
	local cooldown;
	for i=1, numButtons do
		cooldown = getglobal("Gypsy_PetActionButton"..i.."Cooldown");
		local start, duration, enable = GetPetActionCooldown(i);
		CooldownFrame_SetTimer(cooldown, start, duration, enable);
	end
end

function Gypsy_PetActionBar_UpdateBindings ()
	for i=1, numButtons do
		Gypsy_PetActionButton_SetHotkeys(getglobal(petActionPrefix..i));
	end
end

function Gypsy_PetActionBar_ShowGrid ()
	Gypsy_PetActionBar.showgrid = Gypsy_PetActionBar.showgrid + 1;
	for i=1, numButtons do
		getglobal("Gypsy_PetActionButton"..i):Show();
	end
end

function Gypsy_PetActionBar_HideGrid ()
	Gypsy_PetActionBar.showgrid = Gypsy_PetActionBar.showgrid - 1;
	if (Gypsy_PetActionBar.showgrid == 0) then
		local name;
		for i=1, numButtons do
			name = GetPetActionInfo(i);
			if (not name) then
				getglobal("Gypsy_PetActionButton"..i):Hide();
			end
		end
	end
end

--= Pet Action Button Functions =--

function Gypsy_PetActionButton_OnLoad ()
	this:RegisterForDrag("LeftButton", "RightButton");
	this:RegisterForClicks("LeftButtonUp", "RightButtonUp");
	this:RegisterEvent("UPDATE_BINDINGS");
	
	Gypsy_PetActionButton_SetHotkeys();
end

function Gypsy_PetActionButton_OnEvent ()
	Gypsy_PetActionButton_SetHotkeys();
end

function Gypsy_PetActionButton_OnClick (button)
	this:SetChecked(0);
	if (IsShiftKeyDown()) then
		PickupPetAction(this:GetID());
	else
		if (button == "LeftButton") then
			if (IsPetAttackActive(this:GetID())) then
				PetStopAttack();
			else
				CastPetAction(this:GetID());
			end
		else
			TogglePetAutocast(this:GetID());
		end
	end
end

function Gypsy_PetActionButton_OnDragStart ()
	if (LOCK_ACTIONBAR ~= "1" or IsShiftKeyDown()) then
		this:SetChecked(0);
		PickupPetAction(this:GetID());
	end
end

function Gypsy_PetActionButton_OnReceiveDrag ()
	this:SetChecked(0);
	PickupPetAction(this:GetID());
end

function Gypsy_PetActionButton_OnEnter ()
	if (not this.tooltipName) then
		return;
	end
	
	local uber = GetCVar("UberTooltips");
	
	if (this.isToken or uber == "0") then
		if (uber == "0") then
			GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
		else
			GameTooltip_SetDefaultAnchor(GameTooltip, this);
		end
		GameTooltip:SetText(this.tooltipName..color.normal.code.." ("..GetBindingText(GetBindingKey("BONUSACTIONBUTTON"..this:GetID()), "KEY_")..")"..color.close, color:Parse("white"));
		if (this.tooltipSubtext) then
			GameTooltip:AddLine(this.tooltipSubText, "", color:Parse("grey"));
		end
		GameTooltip:Show();
	else
		GameTooltip_SetDefaultAnchor(GameTooltip, this);
		GameTooltip:SetPetAction(this:GetID());
	end
end

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

function Gypsy_PetActionButton_SetHotkeys (button)
	if (this and not button) then
		button = this;
	elseif (not button) then
		return;
	end
	
	local label = getglobal(button:GetName().."HotKey");
	if (saved and saved.bindingLabelMode == "id" and saved.showPetActionLabels == 1) then
		label:SetText(button:GetID());
	elseif (saved and saved.bindingLabelMode ~= "hidden" and saved.showPetActionLabels == 1) then
		local binding = GetBindingText(GetBindingKey("BONUSACTIONBUTTON"..button:GetID()));
		binding = hotlib:CondenseLabel(binding);
		if (saved and saved.bindingLabelMode == "stripped") then
			binding = hotlib:StripCondensedLabel(binding);
		end
		label:SetText(binding);
	else
		label:SetText("");
	end
end

function Gypsy_PetActionButtonAutoCast_OnLoad ()
	this:SetSequence(0);
	this:SetSequenceTime(0, 0);
end