--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--
--|	GypsyMod HotBar - Gypsy_BagBar.lua
--|	Bag button functions
--|	Bag bar functions
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--

--= Libraries =--

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

--= Variables =--

-- Saved variables shortcut table
local saved = nil;

-- Table of bag buttons sorted in left to right order
local bagButtons = {};
bagButtons[1] = "Gypsy_CharacterBag3Slot";
bagButtons[2] = "Gypsy_CharacterBag2Slot";
bagButtons[3] = "Gypsy_CharacterBag1Slot";
bagButtons[4] = "Gypsy_CharacterBag0Slot";
bagButtons[5] = "Gypsy_BackpackButton";

-- Capsule data
local capsuleData = {
	["point"] = "BOTTOM";
	["rel"] = "UIParent";
	["relPoint"] = "BOTTOM";
	["x"] = 0;
	["y"] = 300;
};

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

--= 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.bagbar_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.bagbar_buttonSize;
	end
end

-- Quickly hide all buttons in bagButtons
local function hideAll ()
	for i,v in bagButtons do
		getglobal(v):Hide();
	end
end

-- Hooks to tag on to the end of their respective default functions
local function containerFrame_OnShowHook ()
	if (this:GetID() == 0) then
		Gypsy_BackpackButton:SetChecked(1);
	elseif (this:GetID() <= NUM_BAG_SLOTS) then
		local button = getglobal("Gypsy_CharacterBag"..(this:GetID() - 1).."Slot");
		if (button) then
			button:SetChecked(1);
		end
	end
end

local function containerFrame_OnHideHook ()
	if (this:GetID() == 0) then
		Gypsy_BackpackButton:SetChecked(0);
	else
		local bagButton = getglobal("Gypsy_CharacterBag"..(this:GetID() - 1).."Slot");
		if (bagButton) then
			bagButton:SetChecked(0);
		end
	end
end

local function setItemButtonCountHook (...)
	local button = arg[1];
	local count = arg[2];
	
	if (string.find(button:GetName(), "Gypsy_") and button.isBag and count > 0) then
		if (count > 999) then
			count = count / 1000;
			if (strlen(count) > 3) then
				count = strsub(count, 1, 3);
			end
			count = count.."k";
		end
		
		local countText = getglobal(button:GetName().."Count");
		
		countText:SetText(count);
		
		if (saved and saved.showAmmoCount == 1) then
			countText:Show();
		else
			countText:Hide();
		end
	end
end

utility:Hook("after", "ContainerFrame_OnShow", containerFrame_OnShowHook);
utility:Hook("after", "ContainerFrame_OnHide", containerFrame_OnHideHook);
utility:Hook("after", "SetItemButtonCount", setItemButtonCountHook);

--= BagBar Functions =--

function Gypsy_BagBar_Initialize (player)
	Gypsy_BagBar_LoadConfig(player);

	local args = {};
	args.frame = "Gypsy_BagBar_Capsule";
	if (saved.enabled == 0 or saved.bagbar_shown == 0) then
		args.enabled = 0;
	else
		args.enabled = 1;
	end
	args.locked = saved.bagbar_locked;
	args.doDir = 0;
	if (saved.bagbar_docked == 1) then
		args.orient = saved.actionbar1_orient;
	else
		args.orient = saved.bagbar_orient;
	end
	args.initFunc = "Gypsy_BagBar_Update";
	args.orientFunc = "Gypsy_BagBar_Update";
	args.ordFunc = "Gypsy_BagBar_Update";
	args.menuFunc = "Gypsy_BagBar_DropDown_Toggle";
	args.title = HOTBAR_TEXT:Get("bagbar");
	args.tooltipTitle = HOTBAR_TEXT:Get("bagbar");
	args.tooltipText = HOTBAR_TEXT:Get("capsuleTooltip");	
	args.ratio = getRatio();			
	args.width = hotlib:GetGroupWidth(args.orient, 5, getButtonSize(), getButtonSize(), saved.gap * getRatio());
	args.height = hotlib:GetGroupHeight(args.orient, 5, getButtonSize(), getButtonSize(), saved.gap * getRatio());
	capsule:Register(args);
	
	UIDropDownMenu_Initialize(Gypsy_BagBar_DropDown, Gypsy_BagBar_UpdateDropDown, "MENU");
end

function Gypsy_BagBar_LoadConfig (player)
	saved = GYPSY_SAVED_HOTBAR[player];
	Gypsy_BagBar_UpdateButtonCounts();
end

function Gypsy_BagBar_ValidateSettings ()
	if (saved.actionbar1_shown == 0) then
		saved.bagbar_docked = 0;
	end
end

function Gypsy_BagBar_Update ()
	if (saved.enabled == 1 and saved.bagbar_shown == 1) then			
		local orient, size;
		
		if (saved.bagbar_docked == 1 and saved.actionbar1_shown == 1) then
			orient = saved.actionbar1_orient;
			
			if (saved.setScale == 1) then
				size = saved.size;
			else
				size = saved.actionbar1_buttonSize;
			end
			
			capsule:Disable(Gypsy_BagBar_Capsule);
			
			local x = 0;
			local y = 0;
			
			if (orient == "HORI") then
				x = saved.gap;
			else
				y = -saved.gap;
			end
			
			if (saved.bagbar_backpackOnly == 0) then
				Gypsy_CharacterBag3Slot:ClearAllPoints();
				Gypsy_CharacterBag3Slot:SetPoint(dockedData[orient].point, "Gypsy_ActionButton"..saved.actionbar1_numButtons, dockedData[orient].relPoint, x, y);
			else
				Gypsy_BackpackButton:ClearAllPoints();
				Gypsy_BackpackButton:SetPoint(dockedData[orient].point, "Gypsy_ActionButton"..saved.actionbar1_numButtons, dockedData[orient].relPoint, x, y);
			end
		else
			orient = saved.bagbar_orient;
			size = getButtonSize();
			
			capsule:Enable(Gypsy_BagBar_Capsule);
						
			if (not Gypsy_BagBar_Capsule:IsUserPlaced()) then
				Gypsy_BagBar_Capsule:ClearAllPoints();
				if (saved.actionbar1_shown == 1) then
					Gypsy_BagBar_Capsule:SetPoint("BOTTOMLEFT", "UIParent", "BOTTOMRIGHT", Gypsy_ActionBar1_Capsule:GetRight(), 0);
				else
					Gypsy_BagBar_Capsule:SetPoint("BOTTOMLEFT", "UIParent", "BOTTOMLEFT", GetScreenWidth() * 0.75, 0);
				end
			end
			
			local child;
			
			if (saved.bagbar_backpackOnly == 0) then
				child = Gypsy_CharacterBag3Slot;
			else
				child = Gypsy_BackpackButton;
			end
			
			child:ClearAllPoints();
			child:SetPoint("TOPLEFT", "Gypsy_BagBar_Capsule", "TOPLEFT", capsule.padding, -capsule.padding);
		end
		
		if (saved.bagbar_backpackOnly == 0) then		
			hotlib:ShowButton(Gypsy_CharacterBag3Slot);
			
			for i=2, 5 do
				hotlib:ShowButton(getglobal(bagButtons[i]), orient, saved.gap, bagButtons[i-1]);
			end
		else
			hotlib:ShowButton(Gypsy_BackpackButton);
			
			for i=1, 4 do
				hotlib:HideButton(getglobal(bagButtons[i]));
			end
		end
		
		Gypsy_BagBar_Scale();
				
		if (Gypsy_BagBar_Capsule.initialized and Gypsy_BagBar_Capsule.enabled == 1) then
			local ratio = getRatio();
			Gypsy_BagBar_Capsule.ratio = ratio;
			if (saved.bagbar_backpackOnly == 0) then
				Gypsy_BagBar_Capsule.width = hotlib:GetGroupWidth(orient, 5, size, size, saved.gap * ratio);
				Gypsy_BagBar_Capsule.height = hotlib:GetGroupHeight(orient, 5, size, size, saved.gap * ratio);
			else
				Gypsy_BagBar_Capsule.width = hotlib:GetGroupWidth(orient, 1, size, size, saved.gap * ratio);
				Gypsy_BagBar_Capsule.height = hotlib:GetGroupHeight(orient, 1, size, size, saved.gap * ratio);
			end
			capsule:Size(Gypsy_BagBar_Capsule);
			if (Gypsy_BagBar_Capsule.orient ~= orient) then
				capsule:UpdateOrientation(Gypsy_BagBar_Capsule, orient);
			end
		end
		
		Gypsy_BagBar_UpdateButtonCounts();
	else		
		hideAll();
		capsule:Disable(Gypsy_BagBar_Capsule);
	end
end	

function Gypsy_BagBar_Scale ()
	local size;
	
	if (saved.bagbar_docked == 0 or saved.actionbar1_shown == 0) then
		size = getButtonSize();
	else
		if (saved.setScale == 1) then
			size = saved.size;
		else
			size = saved.actionbar1_buttonSize;
		end
	end
	
	for i=1, 5 do
		hotlib:ScaleButton(getglobal(bagButtons[i]), size);
	end
end

function Gypsy_BagBar_Reset ()
	Gypsy_BagBar_Capsule:SetUserPlaced(0);
end

function Gypsy_BagBar_UpdateButtonCounts ()
	if (saved) then
		for i,v in bagButtons do
			local count = getglobal(v.."Count");
			if (saved.showAmmoCount == 1) then
				count:Show();
			else
				count:Hide();
			end
		end
	end
end 

--= DropDown Functions =--

function Gypsy_BagBar_DropDown_OnShow ()
	UIDropDownMenu_Initialize(this, Gypsy_BagBar_UpdateDropDown, "MENU");
end

function Gypsy_BagBar_DropDown_Toggle ()
	hotlib:ToggleDropDown("Gypsy_BagBar");
end

function Gypsy_BagBar_LoadMenu (level)
	local info = {};
	info.text = HOTBAR_TEXT:Get("show");
	if (saved.bagbar_shown == 1) then
		info.checked = 1;
	end
	info.func = function ()
		if (this.checked) then
			saved.bagbar_shown = 0;
		else
			saved.bagbar_shown = 1;
		end
		Gypsy_BagBar_ValidateSettings();
		Gypsy_BagBar_Update();
		Gypsy_ActionBar_Update();
	end
	UIDropDownMenu_AddButton(info, level);
	info = {};
	info.text = HOTBAR_TEXT:Get("docked");
	if (saved.bagbar_docked == 1 and saved.actionbar1_shown == 1) then
		info.checked = 1;
	end
	info.func = function ()
		if (this.checked) then
			saved.bagbar_docked = 0;
		else
			saved.bagbar_docked = 1;
		end
		Gypsy_BagBar_ValidateSettings();
		Gypsy_BagBar_Update();
		Gypsy_ActionBar_Update();
	end
	if (saved.actionbar1_shown == 0 or saved.bagbar_shown == 0) then
		info.disabled = 1;
	end
	UIDropDownMenu_AddButton(info, level);
	info = {};
	info.text = HOTBAR_TEXT:Get("backpackButtonOnly");
	if (saved.bagbar_backpackOnly == 1) then
		info.checked = 1;
	end
	info.func = function ()
		if (this.checked) then
			saved.bagbar_backpackOnly = 0;
		else
			saved.bagbar_backpackOnly = 1;
		end
		if (saved.bagbar_docked == 1 and saved.actionbar1_shown == 1) then
			Gypsy_ActionBar1_Update();
		else
			Gypsy_BagBar_Update();
		end
	end
	if (saved.bagbar_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 = "bagbar_orientation";
	if (saved.bagbar_shown == 0 or saved.bagbar_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 = "bagbar_buttonsize";
	if (saved.bagbar_shown == 0 or saved.bagbar_docked == 1) then
		info.disabled = 1;
	end
	UIDropDownMenu_AddButton(info, level);
end

function Gypsy_BagBar_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.bagbar_orient == "HORI") then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.bagbar_orient = "HORI";
					capsule:UpdateOrientation(Gypsy_BagBar_Capsule, "HORI");
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = HOTBAR_TEXT:Get("vertical");
			if (saved.bagbar_orient == "VERT") then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.bagbar_orient = "VERT";
					capsule:UpdateOrientation(Gypsy_BagBar_Capsule, "VERT");
				end
			end
			UIDropDownMenu_AddButton(info, 2);
		else
			info = {};
			info.text = "18"..HOTBAR_TEXT:Get("px");
			if (saved.bagbar_buttonSize == 18) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.bagbar_buttonSize = 18;
					if (saved.bagbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_BagBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = "24"..HOTBAR_TEXT:Get("px");
			if (saved.bagbar_buttonSize == 24) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.bagbar_buttonSize = 24;
					if (saved.bagbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_BagBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = "30"..HOTBAR_TEXT:Get("px");
			if (saved.bagbar_buttonSize == 30) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.bagbar_buttonSize = 30;
					if (saved.bagbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_BagBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = "36"..HOTBAR_TEXT:Get("px");
			if (saved.bagbar_buttonSize == 36) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.bagbar_buttonSize = 36;
					if (saved.bagbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_BagBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = "42"..HOTBAR_TEXT:Get("px");
			if (saved.bagbar_buttonSize == 42) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.bagbar_buttonSize = 42;
					if (saved.bagbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_BagBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);
			info = {};
			info.text = "48"..HOTBAR_TEXT:Get("px");
			if (saved.bagbar_buttonSize == 48) then
				info.checked = 1;
			end
			info.func = function ()
				if (not this.checked) then
					saved.bagbar_buttonSize = 48;
					if (saved.bagbar_docked == 1) then
						Gypsy_ActionBar1_Update();
					else
						Gypsy_BagBar_Update();
					end
				end
			end
			UIDropDownMenu_AddButton(info, 2);			
		end
		return;
	end
	
	info = {};
	info.text = HOTBAR_TEXT:Get("bagbar");
	info.isTitle = 1;
	info.notCheckable = 1;
	UIDropDownMenu_AddButton(info);
	Gypsy_BagBar_LoadMenu();
end

--= BagSlotButton Functions =--

local function bagClickRoutine ()
	local id = this:GetID();
	local translatedID = id - CharacterBag0Slot:GetID() + 1;
	local hadItem = PutItemInBag(id);
	
	if (not hadItem) then
		ToggleBag(translatedID);
		PlaySound("BAGMENUBUTTONPRESS");		
	end
	
	local isVisible = 0;
	
	for i=1, NUM_CONTAINER_FRAMES, 1 do
		local frame = getglobal("ContainerFrame"..i);
		if ((frame:GetID() == translatedID) and frame:IsVisible()) then
			isVisible = 1;
			break;
		end
	end
	
	this:SetChecked(isVisible);
end

function Gypsy_BagSlotButton_OnLoad ()
	this:RegisterEvent("UNIT_INVENTORY_CHANGED");
	this:RegisterEvent("ITEM_LOCK_CHANGED");
	this:RegisterEvent("CURSOR_UPDATE");
	this:RegisterEvent("BAG_UPDATE_COOLDOWN");
	this:RegisterEvent("SHOW_COMPARE_TOOLTIP");
	this:RegisterEvent("UPDATE_INVENTORY_ALERTS");
	this:RegisterEvent("BAG_UPDATE");
	this:RegisterForDrag("LeftButton");
	this:RegisterForClicks("LeftButtonUp", "RightButtonUp");
	
	local slotName = this:GetName();
	slotName = string.gsub(slotName, "Gypsy_", "");
	
	local id, textureName = GetInventorySlotInfo(strsub(slotName,10));
	this:SetID(id);
	
	local texture = getglobal("Gypsy_"..slotName.."IconTexture");
	texture:SetTexture(textureName);
	
	this.backgroundTextureName = textureName;
	
	PaperDollItemSlotButton_Update();
	this.isBag = 1;
end

function Gypsy_BagSlotButton_OnClick ()
	if (IsShiftKeyDown()) then
		BagSlotButton_OnShiftClick();
	else
		bagClickRoutine();
	end
end

function Gypsy_BagSlotButton_OnDragStart ()
	local translatedID = this:GetID() - CharacterBag0Slot:GetID() + 1;
	PickupBagFromSlot(this:GetID());
	PlaySound("BAGMENUBUTTONPRESS");
	
	local isVisible = 0;
	
	for i=1, NUM_CONTAINER_FRAMES, 1 do
		local frame = getglobal("ContainerFrame"..i);
		if ((frame:GetID() == translatedID) and frame:IsVisible()) then
			isVisible = 1;
			break;
		end
	end
	
	this:SetChecked(isVisible);
end

function Gypsy_BagSlotButton_OnRecieveDrag ()
	bagClickRoutine();
end

function Gypsy_BagSlotButton_OnEnter ()
	GameTooltip:SetOwner(this, "ANCHOR_LEFT");
	
	if (GameTooltip:SetInventoryItem("player", this:GetID())) then
		local bindingKey = GetBindingKey("TOGGLEBAG"..(4 -  (this:GetID() - CharacterBag0Slot:GetID())));
		if (bindingKey) then
			GameTooltip:AppendText(" "..color.normal.code.."("..bindingKey..")"..color.close);
		end
	else
		GameTooltip:SetText(TEXT(EQUIP_CONTAINER), color:Parse("white"));
	end
end

--= BackpackButton Functions =--

local function backpackClickRoutine ()
	if (not PutItemInBackpack()) then
		ToggleBackpack();
	end
	
	local isVisible = 0;
	
	for i=1, NUM_CONTAINER_FRAMES, 1 do
		local frame = getglobal("ContainerFrame"..i);
		if ((frame:GetID() == 0) and frame:IsVisible()) then
			isVisible = 1;
			break;
		end
	end
	
	this:SetChecked(isVisible);
end

function Gypsy_BackpackButton_OnLoad ()
	this:RegisterForClicks("LeftButtonUp", "RightButtonUp");
	
	Gypsy_BackpackButtonIconTexture:SetTexture("Interface\\Buttons\\Button-Backpack-Up");
end

function Gypsy_BackpackButton_OnClick ()
	if (IsShiftKeyDown()) then
		OpenAllBags();
	else
		backpackClickRoutine();
	end
end

function Gypsy_BackpackButton_OnRecieveDrag ()
	backpackClickRoutine();
end

function Gypsy_BackpackButton_OnEnter ()
	GameTooltip:SetOwner(this, "ANCHOR_LEFT");
	GameTooltip:SetText(TEXT(BACKPACK_TOOLTIP), color:Parse("white"));
	
	local keyBinding = GetBindingKey("TOGGLEBACKPACK");
	if (keyBinding) then
		GameTooltip:AppendText(" "..color.normal.code.."("..keyBinding..")"..color.close);
	end
end

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