--
--  AutoBar
--  Copyright 2004, 2005, 2006 original author. 
--  Copyright is expressly not transferred to Blizzard.
-- 
--  Configurable set of 12 buttons that seeks out configured items 
--  in your pack for use. Intended primarily for consumables. Not 
--  for use with spells, skills, trinkets, or powers.
--
--  Author: Marc aka Saien on Hyjal
--  WOWSaien@gmail.com
--  http://64.168.251.69/wow
--
--  2005.01.12
--    Selfcast is back
--    AutoBar re-parented so it hides with an Alt-Z
--    Configuration checkbox to hide Keybind text 
--    Configuration checkbox to hide Count text
--    Configuration checkbox to show empty buttons
--    Keybind text and count text scales with button width.
--    Can now open configuration while dead.
--    "Num Pad" key bindings are now shortened to just N in display.
--    Removed /ab as a shortcut for the depreciated slash commands.
--    Fixed Mana potion hp restriction - should be mana restriction
--    Minimum button width/height set to 9 pixels instead of 18.
--  2005.01.06
--    Release of complete re-write.
--

AUTOBAR_VERSION = "2006.01.12" -- Notice the cleverly disguised date.
------------------------------------
BINDING_HEADER_AUTOBAR_SEP = "Auto Bar";
BINDING_NAME_AUTOBAR_CONFIG = "Configuration Window";
BINDING_NAME_AUTOBAR_BUTTON1 = "Button 1";
BINDING_NAME_AUTOBAR_BUTTON2 = "Button 2";
BINDING_NAME_AUTOBAR_BUTTON3 = "Button 3";
BINDING_NAME_AUTOBAR_BUTTON4 = "Button 4";
BINDING_NAME_AUTOBAR_BUTTON5 = "Button 5";
BINDING_NAME_AUTOBAR_BUTTON6 = "Button 6";
BINDING_NAME_AUTOBAR_BUTTON7 = "Button 7";
BINDING_NAME_AUTOBAR_BUTTON8 = "Button 8";
BINDING_NAME_AUTOBAR_BUTTON9 = "Button 9";
BINDING_NAME_AUTOBAR_BUTTON10 = "Button 10";
BINDING_NAME_AUTOBAR_BUTTON11 = "Button 11";
BINDING_NAME_AUTOBAR_BUTTON12 = "Button 12";
------------------------------------
AUTOBAR_MAXBUTTONS = 12;
-----------------------------------
AutoBar_Debug = nil;
AutoBar_Player = nil; -- global
--
local AutoBar_ConfigLoaded = nil;
local AutoBar_SearchedForItems = {};
local AutoBar_ButtonItemList = {};
local AutoBar_ButtonItemList_Reversed = {};
local AutoBar_Buttons_CurrentItems = {};
--
local AutoBar_InWorld = nil;
local AutoBar_InCombat = nil; -- For item use restrictions
------------------------------------

local function AutoBar_LinkDecode(link)
	if (link) then
		local _, _, id, name = string.find(link,"|Hitem:(%d+):%d+:%d+:%d+|h%[([^]]+)%]|h|r$");
		if (id and name) then
			return name, tonumber(id);
		end
	end
end

local function AutoBar_ConfigInit()
	if (not AutoBar_Config) then AutoBar_Config = {}; end
	if (not AutoBar_Config[AutoBar_Player]) then AutoBar_Config[AutoBar_Player] = {}; end
	---
	if (AutoBar_Config[AutoBar_Player].docked and AutoBar_Config[AutoBar_Player].scaling and 
	    AutoBar_Config[AutoBar_Player].rows and AutoBar_Config[AutoBar_Player].columns) then
		-- Config is from pre re-write. Not upgrading.
 		AutoBar_Config[AutoBar_Player] = {};
		AutoBar_Msg("Config for this character is old version. Clearing. No attempt to upgrade config is being done.");
	end
	---
	if (not AutoBar_Config[AutoBar_Player].buttons) then
		local _,class = UnitClass("player");
		AutoBar_Config[AutoBar_Player].buttons = {};
		AutoBar_Config[AutoBar_Player].buttons[1] = { "BANDAGES", "ALTERAC_BANDAGES", "WARSONG_BANDAGES", "ARATHI_BANDAGES", "UNGORO_RESTORE"};
		AutoBar_Config[AutoBar_Player].buttons[2] = { "HEALPOTIONS", "REJUVENATION_POTIONS", "WHIPPER_ROOT", "NIGHT_DRAGONS_BREATH", "PVP_HEALPOTIONS", "ALTERAC_HEAL", "HEALTHSTONE" };
		if (class == "WARRIOR") then
			AutoBar_Config[AutoBar_Player].buttons[3] = "RAGEPOTIONS";
		elseif (class == "ROGUE") then
			AutoBar_Config[AutoBar_Player].buttons[3] = "ENERGYPOTIONS";
		elseif (class == "MAGE") then
			AutoBar_Config[AutoBar_Player].buttons[3] = { "MANAPOTIONS", "REJUVENATION_POTIONS", "NIGHT_DRAGONS_BREATH", "PVP_MANAPOTIONS", "ALTERAC_MANA", "MANASTONE" };
		else
			AutoBar_Config[AutoBar_Player].buttons[3] = { "MANAPOTIONS", "REJUVENATION_POTIONS", "NIGHT_DRAGONS_BREATH", "PVP_MANAPOTIONS", "ALTERAC_MANA"  };
		end
		if (class ~= "ROGUE" and class ~= "WARRIOR") then
			AutoBar_Config[AutoBar_Player].buttons[4] = { "WATER", "WATER_CONJURED" };
		end
		AutoBar_Config[AutoBar_Player].buttons[5] = { "FOOD", "FOOD_STAMINA", "FOOD_CONJURED" };
		AutoBar_Config[AutoBar_Player].buttons[AUTOBAR_MAXBUTTONS] = "HEARTHSTONE";
	end
	if (not AutoBar_Config[AutoBar_Player].display) then
		AutoBar_Config[AutoBar_Player].display = {};
	end
	AutoBar_ConfigUpdated();
end

local function AutoBar_BuildItemList()
	local function AddItemInfo(identifier, buttonnum)
		if (AutoBar_Category_Info[identifier] and AutoBar_Category_Info[identifier].items) then
			local idx,j;
			for idx, j in AutoBar_Category_Info[identifier].items do
				if (AutoBar_SearchedForItems[j]) then
					table.insert(AutoBar_SearchedForItems[j], buttonnum);
					table.insert(AutoBar_ButtonItemList[buttonnum], j);
				else
					AutoBar_SearchedForItems[j] = { buttonnum, identifier, idx };
					table.insert(AutoBar_ButtonItemList[buttonnum], j);
				end
			end
		elseif (not AutoBar_SearchedForItems[identifier]) then
			AutoBar_SearchedForItems[identifier] = { buttonnum, identifier, 0 };
			table.insert(AutoBar_ButtonItemList[buttonnum], identifier);
		end
	end
	AutoBar_SearchedForItems = {};
	AutoBar_ButtonItemList_Reversed = {};
	local idx;
	for idx = 1, AUTOBAR_MAXBUTTONS, 1 do
		if (AutoBar_Config[AutoBar_Player].buttons[idx]) then
			local i, j;
			AutoBar_ButtonItemList[idx] = {};
			AutoBar_ButtonItemList_Reversed[idx] = {};
			if (type(AutoBar_Config[AutoBar_Player].buttons[idx]) == "table") then
				for i, j in AutoBar_Config[AutoBar_Player].buttons[idx] do
					AddItemInfo (j, idx);
				end
			else
				AddItemInfo (AutoBar_Config[AutoBar_Player].buttons[idx], idx);
			end
			for i, j in AutoBar_ButtonItemList[idx] do
				AutoBar_ButtonItemList_Reversed[idx][j] = i;
			end
		end
	end
end

function AutoBar_Button_GetDisplayItem(buttonnum)
	local idx, bag, slot, rank, itemid, category, categoryidx, acceptable, cooldowntime;
	local cooldownidx, start, duration, enable, fallback;
	if (AutoBar_Buttons_CurrentItems[buttonnum]) then
		idx = table.getn(AutoBar_Buttons_CurrentItems[buttonnum]);
	else
		idx = 0;
	end
	while (idx > 0 and not acceptable) do
		bag = AutoBar_Buttons_CurrentItems[buttonnum][idx].items[1][1];
		slot = AutoBar_Buttons_CurrentItems[buttonnum][idx].items[1][2];
		rank = AutoBar_Buttons_CurrentItems[buttonnum][idx].rank;
		itemid = AutoBar_ButtonItemList[buttonnum][rank];
		if (AutoBar_SearchedForItems[itemid]) then 
			category = AutoBar_SearchedForItems[itemid][2];
			categoryidx = AutoBar_SearchedForItems[itemid][3];
		else
			category = nil;
			categoryidx = nil;
		end
		--
		start, duration, enable = GetContainerItemCooldown(bag, slot);
		if (start > 0 and duration > 0) then
			local tmp = start - GetTime() + duration;
			if (not cooldowntime or tmp < cooldowntime) then
				cooldowntime = tmp;
				cooldownidx = idx;
			end
			idx = idx - 1;
		elseif (AutoBar_Category_Info[category]) then
			if (not fallback) then 
				fallback = idx; 
			end
			if (AutoBar_Category_Info[category].combatonly and not AutoBar_InCombat) then
				idx = idx - 1;
			elseif (AutoBar_Category_Info[category].noncombat and AutoBar_InCombat) then
				idx = idx - 1;
			elseif (AutoBar_Category_Info[category].location and AutoBar_Category_Info[category].location ~= GetZoneText()) then
				idx = idx - 1;
			elseif (AutoBar_Category_Info[category].limit) then
				local losthp = UnitHealthMax("player") - UnitHealth("player");
				local lostmana = UnitManaMax("player") - UnitMana("player");
				if (UnitPowerType("player") ~= 0 ) then
					if (UnitClass("player") == "Druid") then
						-- Can't check mana in druid forms
						lostmana = 0;
					else
						-- Class doesn't have mana, don't limit
						lostmana = 10000;
					end
				end
				if (AutoBar_Category_Info[category].limit.downhp and AutoBar_Category_Info[category].limit.downhp[categoryidx] > losthp) then
					idx = idx - 1
				elseif (AutoBar_Category_Info[category].limit.downmana and AutoBar_Category_Info[category].limit.downmana[categoryidx] > lostmana) then
					idx = idx - 1
				else
					acceptable = true;
				end
			else
				acceptable = true;
			end
		else
			acceptable = true;
		end
	end
	if (not acceptable) then
		if (fallback) then
			idx = fallback;
		elseif (cooldownidx) then
			idx = cooldownidx;
		elseif (AutoBar_Buttons_CurrentItems[buttonnum]) then
			idx = table.getn(AutoBar_Buttons_CurrentItems[buttonnum]);
		else
			idx = nil;
		end
	end
	--
	if (idx) then
		bag = AutoBar_Buttons_CurrentItems[buttonnum][idx].items[1][1];
		slot = AutoBar_Buttons_CurrentItems[buttonnum][idx].items[1][2];
		rank = AutoBar_Buttons_CurrentItems[buttonnum][idx].rank;
	else
		bag = nil; slot = nil; rank = nil;
	end
	if (AutoBar_ButtonItemList[buttonnum]) then
		itemid = AutoBar_ButtonItemList[buttonnum][rank];
		if (AutoBar_SearchedForItems[itemid]) then 
			category = AutoBar_SearchedForItems[itemid][2];
			categoryidx = AutoBar_SearchedForItems[itemid][3];
		else
			category = nil;
			categoryidx = nil;
		end
	else
		itemid = nil; category = nil; categoryidx = nil;
	end
	return bag, slot, rank, itemid, category, categoryidx, idx, acceptable, cooldowntime;
end

function AutoBar_Button_UpdateButtons()
	local buttonnum, i, button, icon, normaltexture, counttxt, bag, slot, idx, items;
	local hotkey, count, tmpcount, keyText, actioncommand;
	for buttonnum = 1, AUTOBAR_MAXBUTTONS, 1 do
		button = getglobal("AutoBar_Button"..buttonnum);
		icon = getglobal("AutoBar_Button"..buttonnum.."Icon");
		normaltexture = getglobal("AutoBar_Button"..buttonnum.."NormalTexture");
		counttxt = getglobal("AutoBar_Button"..buttonnum.."Count");
		hotkey = getglobal("AutoBar_Button"..buttonnum.."HotKey");
		if (not button.forcehidden and button.effectiveButton) then
			button:Show();
			bag, slot,_,_,_,_,idx,enabled = AutoBar_Button_GetDisplayItem(button.effectiveButton)
			if (bag and slot) then
				items = AutoBar_Buttons_CurrentItems[button.effectiveButton][idx].items
				count = 0;
				for i, bagslot in items do
					_, tmpcount = GetContainerItemInfo(bagslot[1], bagslot[2]);
					if (tmpcount) then
						count = count + tmpcount;
					end
				end
				icon:SetTexture(GetContainerItemInfo(bag,slot));
				if (count > 1) then
					counttxt:SetText(count);
				else
					counttxt:SetText("");
				end
				if (enabled) then
					icon:SetVertexColor(1,1,1);
					normaltexture:SetVertexColor(1,1,1);
				else
					icon:SetVertexColor(0.4,0.4,0.4);
					normaltexture:SetVertexColor(1,1,1);
				end
				actioncommand = "AUTOBAR_BUTTON"..button.effectiveButton;
				if (actioncommand) then
					keyText = GetBindingKey(actioncommand);
					if (keyText) then
						keyText = string.gsub(keyText, "CTRL", "C");
						keyText = string.gsub(keyText, "ALT", "A");
						keyText = string.gsub(keyText, "SHIFT", "S");
						keyText = string.gsub(keyText, "Num Pad", "N");
						hotkey:SetText(keyText);
					else
						hotkey:SetText("");
					end
				end
			else
				icon:SetTexture("");
				counttxt:SetText("");
				hotkey:SetText("");
			end
		else
			button:Hide();
		end
	end
end

local function AutoBar_AssignButtons()
	local displayButton = 0;
	local buttonidx, buttoninfo, rankidx, items;
	for buttonidx = 1, AUTOBAR_MAXBUTTONS, 1 do
		if (AutoBar_Config[AutoBar_Player].display.showemptybuttons or AutoBar_Buttons_CurrentItems[buttonidx]) then
			displayButton = displayButton + 1;
			local button = getglobal("AutoBar_Button"..displayButton);
			button.effectiveButton = buttonidx;
		end
	end
	for buttonidx = displayButton+1, AUTOBAR_MAXBUTTONS, 1 do
		local button = getglobal("AutoBar_Button"..buttonidx);
		button.effectiveButton = nil;
	end
	AutoBar_Button_UpdateButtons();
end

local function AutoBar_UpdateCategoryNameToID(name,id)
	local buttonnum, idx;
	for buttonnum = 1, AUTOBAR_MAXBUTTONS, 1 do
		if (AutoBar_Config[AutoBar_Player].buttons[buttonnum]) then
			if (type(AutoBar_Config[AutoBar_Player].buttons[buttonnum]) == "table") then
				for idx in AutoBar_Config[AutoBar_Player].buttons[buttonnum] do
					if (AutoBar_Config[AutoBar_Player].buttons[buttonnum][idx] == name) then
						AutoBar_Config[AutoBar_Player].buttons[buttonnum][idx] = id;
						AutoBar_Msg("Updating multi item button #",buttonnum," item #",idx," to use itemid instead of item name.");
					end
				end
			elseif (AutoBar_Config[AutoBar_Player].buttons[buttonnum] == name) then
				AutoBar_Config[AutoBar_Player].buttons[buttonnum] = id;
				AutoBar_Msg("Updating single item button #",buttonnum," to use itemid instead of item name.");
			end
		end
	end
end

function AutoBar_ScanBags(specificbag)
	local function ClearOutBag(bag)
		local buttonnum, idx, i, bagslot, newitemlist, newranks;
		for buttonnum = 1, AUTOBAR_MAXBUTTONS, 1 do
			if (AutoBar_Buttons_CurrentItems[buttonnum]) then 
				newranks = {};
				for idx in AutoBar_Buttons_CurrentItems[buttonnum] do
					newitemlist = {};
					for i, bagslot in AutoBar_Buttons_CurrentItems[buttonnum][idx].items do
						if (bag ~= bagslot[1]) then
							table.insert(newitemlist,bagslot); 
						end
					end
					if (table.getn(newitemlist) > 0) then
						AutoBar_Buttons_CurrentItems[buttonnum][idx].items = newitemlist;
						table.insert(newranks,AutoBar_Buttons_CurrentItems[buttonnum][idx]);
					end
				end
				if (table.getn(newranks) == 0) then
					AutoBar_Buttons_CurrentItems[buttonnum] = nil;
				else
					AutoBar_Buttons_CurrentItems[buttonnum] = newranks;
				end
			end
		end
	end
	local function AddItem(buttonnum, rank, bag, slot)
		if (AutoBar_Buttons_CurrentItems[buttonnum]) then 
			local idx, rec, findRank;
			for idx, rec in AutoBar_Buttons_CurrentItems[buttonnum] do
				if (rec.rank == rank) then
					findRank = idx;
				end
			end
			if (findRank) then
				table.insert(AutoBar_Buttons_CurrentItems[buttonnum][findRank].items, { bag, slot } );
			else
				table.insert(AutoBar_Buttons_CurrentItems[buttonnum],
					{
				 		["rank"] = rank,
				 		["items"] = { { bag, slot } }
					}
				);
			end
		else
			AutoBar_Buttons_CurrentItems[buttonnum] = {
				[1] = {
					["rank"] = rank,
					["items"] = { { bag, slot } }
				},
			};
		end
	end
	local function SortByRank(a,b)
		if (a and b and a.rank and b.rank) then
			return a.rank < b.rank;
		else
			return true;
		end
	end

	local bag, slot, name, id, i;
	local minbag,maxbag = 0, 4;
	if (specificbag) then 
		minbag = specificbag; 
		maxbag = specificbag; 
		ClearOutBag(specificbag);
	else
		AutoBar_Buttons_CurrentItems = {};
	end
	-- AutoBar_Buttons_CurrentItems = {
	--	buttonnum = {
	--		idx = {
	--			"rank" = ranknum,
	--			"items" = { {bag,slot}, {bag,slot}, {bag, slot} }
	--		},
	--	},
	--};
	for bag = minbag, maxbag, 1 do
		for slot = 1, GetContainerNumSlots(bag), 1 do
			name, id = AutoBar_LinkDecode(GetContainerItemLink(bag,slot));
			if (name and AutoBar_SearchedForItems[name] and id and not AutoBar_SearchedForItems[id]) then
				AutoBar_SearchedForItems[id] = { AutoBar_SearchedForItems[name][1], AutoBar_SearchedForItems[name][2], AutoBar_SearchedForItems[name][3] };
				AutoBar_UpdateCategoryNameToID(name,id);
			end
			if (id and AutoBar_SearchedForItems[id]) then
				local button = AutoBar_SearchedForItems[id][1];
				local rank = AutoBar_ButtonItemList_Reversed[button][id];
				AddItem(button, rank, bag, slot)
				if (AutoBar_SearchedForItems[id][4]) then
					for i = 4, table.getn(AutoBar_SearchedForItems[id]), 1 do
						button = AutoBar_SearchedForItems[id][i];
						rank = AutoBar_ButtonItemList_Reversed[button][id];
						AddItem(button, rank, bag, slot)
					end
				end
			end
		end
	end
	local buttonnum;
	for buttonnum = 1, AUTOBAR_MAXBUTTONS, 1 do
	 	if (AutoBar_Buttons_CurrentItems[buttonnum]) then
			table.sort(AutoBar_Buttons_CurrentItems[buttonnum], SortByRank);
	 	end
	end
	AutoBar_AssignButtons();
end

------------------------------------

function AutoBar_OnLoad()
	AutoBar_Player = UnitName("player").." - "..GetCVar("realmName");

	this:RegisterEvent("PLAYER_ENTERING_WORLD"); 
	this:RegisterEvent("PLAYER_LEAVING_WORLD"); 
	--
	this:RegisterEvent("BAG_UPDATE");
	this:RegisterEvent("UPDATE_BINDINGS");
	-- 
	-- For item use restrictions
	this:RegisterEvent("ZONE_CHANGED_NEW_AREA");
	this:RegisterEvent("PLAYER_REGEN_ENABLED");
	this:RegisterEvent("PLAYER_REGEN_DISABLED");
	this:RegisterEvent("UNIT_MANA");
	this:RegisterEvent("UNIT_HEALTH");
	this:RegisterEvent("PLAYER_ALIVE");
	--
end

function AutoBar_OnEvent(event)
	if (event == "PLAYER_ENTERING_WORLD") then
		AutoBar_InCombat = nil;
		if (not AutoBar_ConfigLoaded) then
			AutoBar_ConfigInit();
			AutoBar_ConfigLoaded = 1;
			AutoBar_ScanBags();
		end
		if (not AutoBar_InWorld) then
			AutoBar_InWorld = 1;
			AutoBar_ScanBags();
			AutoBar_Button_UpdateButtons();
		end
	elseif (event == "PLAYER_LEAVING_WORLD") then
		AutoBar_InWorld = nil;
	elseif (AutoBar_InWorld) then
		if (event == "BAG_UPDATE") then
			if (arg1 < 5) then
				AutoBar_ScanBags(arg1);
			end
		elseif (event == "UPDATE_BINDINGS") then
			AutoBar_Button_UpdateButtons();
		elseif (event == "PLAYER_ALIVE") then
			AutoBar_Button_UpdateButtons();
		elseif ((event == "UNIT_MANA" or event == "UNIT_HEALTH") and arg1=="player") then
			AutoBar_Button_UpdateButtons();
		elseif (event == "PLAYER_REGEN_ENABLED") then
			AutoBar_InCombat = nil;
			AutoBar_Button_UpdateButtons();
		elseif (event == "PLAYER_REGEN_DISABLED") then
			AutoBar_InCombat = 1;
			AutoBar_Button_UpdateButtons();
		elseif (event == "ZONE_CHANGED_NEW_AREA") then
			AutoBar_Button_UpdateButtons();
		end
	end
end

------------------------------------

function AutoBar_UseButton(num)
	local bag, slot, rank, itemid, category, categoryidx, idx, acceptable = AutoBar_Button_GetDisplayItem(num);
	UseContainerItem(bag,slot);
	if (AutoBar_Category_Info[category] and AutoBar_Category_Info[category].targetted == "WEAPON" and SpellIsTargeting()) then
		PickupInventoryItem(GetInventorySlotInfo("MainHandSlot"));
	elseif (AutoBar_Category_Info[category] and AutoBar_Category_Info[category].targetted and AutoBar_Config[AutoBar_Player].smartselfcast and AutoBar_Config[AutoBar_Player].smartselfcast[category] and SpellIsTargeting()) then
		SpellTargetUnit("player");
	end
end


function AutoBar_Button_OnClick(mousebutton, updown, override)
	local button;
	if (override) then
		button = getglobal("AutoBar_Button"..override);
	else
		button = this;
	end
	button:SetChecked(0);
	if (AutoBar.moving) then
		if (updown == "CLICK") then
			AutoBar.moving = nil;
			AutoBar:StopMovingOrSizing();
			AutoBar_Config[AutoBar_Player].display.position = {};
			AutoBar_Config[AutoBar_Player].display.position.x, 
			AutoBar_Config[AutoBar_Player].display.position.y = AutoBar:GetCenter();
			AutoBar:SetMovable(0);
		end
	elseif (updown == "CLICK") then
		local bag, slot, rank, itemid, category, categoryidx, idx, acceptable = AutoBar_Button_GetDisplayItem(button.effectiveButton);
		UseContainerItem(bag,slot);
		if (AutoBar_Category_Info[category] and AutoBar_Category_Info[category].targetted == "WEAPON" and SpellIsTargeting()) then
			if (mousebutton == "LeftButton") then
				PickupInventoryItem(GetInventorySlotInfo("MainHandSlot"));
			elseif (mousebutton == "RightButton") then
				PickupInventoryItem(GetInventorySlotInfo("SecondaryHandSlot"));
			end
		elseif (AutoBar_Category_Info[category] and AutoBar_Category_Info[category].targetted and AutoBar_Config[AutoBar_Player].smartselfcast and AutoBar_Config[AutoBar_Player].smartselfcast[category] and SpellIsTargeting()) then
			SpellTargetUnit("player");
		end
	elseif (mousebutton == "RightButton" and updown == "DOWN" and IsControlKeyDown()) then
		if (not AutoBar_Config[AutoBar_Player].display.docking) then
			AutoBar.moving = true;
			AutoBar:SetMovable(1);
			AutoBar:StartMoving();
		end
	end
end

function AutoBar_Button_SetTooltip(button, elapsed)
	if (not button) then button = this; end
	if (button:GetParent().updateTooltip and elapsed) then
		button.updateTooltip = button.updateTooltip - elapsed;
		if (button.updateTooltip > 0) then return; end
	end

	if (button.effectiveButton) then
		if (GetCVar("UberTooltips") == "1") then
			GameTooltip_SetDefaultAnchor(GameTooltip, button);
		else
			GameTooltip:SetOwner(button, "ANCHOR_RIGHT");
		end
		button.updateTooltip = nil;

		local bag, slot, rank, itemid, category, categoryidx = AutoBar_Button_GetDisplayItem(button.effectiveButton)
		if (bag and slot) then
			GameTooltip:SetBagItem(bag, slot);
			if (AutoBar_Debug) then
				if (rank) then
					GameTooltip:AddLine("DISPLAYED RANK: "..rank);
				end
				if (itemid) then
					GameTooltip:AddLine("DISPLAYED ITEMID: "..itemid);
				end
				if (category) then
					GameTooltip:AddLine("DISPLAYED CATEGORY: "..category);
				end
				if (categoryidx) then
					GameTooltip:AddLine("DISPLAYED CATEGORYIDX: "..categoryidx);
				end
			end
			local start, duration, enable = GetContainerItemCooldown(bag, slot);
			if (start > 0 and duration > 0) then
				button.updateTooltip = TOOLTIP_UPDATE_TIME;
			end
	
			GameTooltip:AddLine("");
			local rankidx, idx, itemident, bagslot, count, tmpcount, name, itemid, msg;
			local start, duration, enable;
			for rankidx, itemident in AutoBar_Buttons_CurrentItems[button.effectiveButton] do
				count = 0;
				for idx, bagslot in itemident.items do
					_, tmpcount = GetContainerItemInfo(bagslot[1], bagslot[2]);
					count = count + tmpcount;
				end
				name,itemid = AutoBar_LinkDecode(GetContainerItemLink(itemident.items[1][1], itemident.items[1][2]));
				category = AutoBar_SearchedForItems[itemid][2];
				start, duration, enable = GetContainerItemCooldown(itemident.items[1][1], itemident.items[1][2]);
				msg = name.." (Count: "..count..")";
				if (AutoBar_Debug) then
					msg = msg.." ["..itemident.items[1][1]..","..itemident.items[1][2].."]";
					if (rank) then
						msg = msg.." rank="..itemident.rank;
					end
					if (cat) then
						msg = msg.." cat="..category;
					end
				end
				if (category == itemid and categoryidx == 0) then
					msg = msg.." [Custom Item]"
				end
				if (AutoBar_Category_Info[category]) then
					if (AutoBar_Category_Info[category].combatonly) then
						msg=msg.." [In Combat Only]";
					end
					if (AutoBar_Category_Info[category].noncombat) then
						msg=msg.." [Non Combat Only]";
					end
					if (AutoBar_Category_Info[category].limit) then
						msg=msg.." [Limited Usage]";
					end
				end
				if (start > 0 and duration > 0) then
					msg = msg.." [Cooldown]";
				end
				GameTooltip:AddLine(msg);
				if (category and AutoBar_Category_Info[category] and AutoBar_Category_Info[category].targetted == "WEAPON") then
					GameTooltip:AddLine("\n(Left Click to apply to Main Hand weapon\nRight Click to apply to OffHand weapon)");
				end
			end
			GameTooltip:Show();
		end
	end
end

------------------------------------

function AutoBar_GetTexture(id)
	if (not id) then return ""; end
	if (type(id) == "table" and id[1]) then id = id[1]; end
	if (id and AutoBar_Category_Info[id]) then
		if (AutoBar_Category_Info[id].texture) then
			return "Interface\\Icons\\"..AutoBar_Category_Info[id].texture;
		else
			id = AutoBar_Category_Info[id].items[1];
		end
	end
	if (type(id)=="number" and id > 0) then
		local _,_,_,_,_,_,_,_,texture = GetItemInfo(tonumber(id));
		if (texture) then return texture; end
	end
	return "Interface\\Icons\\INV_Misc_Gift_01";
end

function AutoBar_Msg(...)
	local message = "";
	for i = 1, arg.n, 1 do
		if (type(arg[i]) == "string" or type(arg[i]) == "number") then
			message = message..arg[i];
		else
			message = message..string.upper(type(arg[i]));
		end
	end
	ChatFrame1:AddMessage("AutoBar: "..message);
end

function AutoBar_ConfigUpdated()
	AutoBar_BuildItemList();
	AutoBar_ScanBags();
	AutoBar_SetupVisual();
end

function AutoBar_SetupVisual()
	local rows = AutoBar_Config[AutoBar_Player].display.rows;
	local columns = AutoBar_Config[AutoBar_Player].display.columns;
	local gapping = AutoBar_Config[AutoBar_Player].display.gapping;
	local alpha = AutoBar_Config[AutoBar_Player].display.alpha;
	local buttonwidth = AutoBar_Config[AutoBar_Player].display.buttonwidth;
	local buttonheight = AutoBar_Config[AutoBar_Player].display.buttonheight;
	local dockshiftx = AutoBar_Config[AutoBar_Player].display.dockshiftx;
	local dockshifty = AutoBar_Config[AutoBar_Player].display.dockshifty;
	--
	if (not rows) then rows = 1; end
	if (not columns) then columns = 6; end
	if (not gapping) then gapping = 6; end
	if (not alpha) then alpha = 1; end
	if (not buttonwidth) then buttonwidth = 36 end
	if (not buttonheight) then buttonheight = 36; end
	if (not dockshiftx) then dockshiftx = 0; end
	if (not dockshifty) then dockshifty = 0; end
	--
	AutoBar:Show();
	AutoBar:ClearAllPoints();
	if (AutoBar_Config[AutoBar_Player].display.framestrata) then
		AutoBar:SetFrameStrata(AutoBar_Config[AutoBar_Player].display.framestrata);
	else
		if (AutoBar_Config[AutoBar_Player].display.docking == "MAINMENU") then
			AutoBar:SetFrameStrata("HIGH");
		else
			AutoBar:SetFrameStrata("LOW");
		end
	end
	if (AutoBar_Config[AutoBar_Player].display.docking) then
		if (AutoBar_Config[AutoBar_Player].display.docking == "MAINMENU") then
			AutoBar:SetPoint("BOTTOMLEFT","MainMenuBarArtFrame","BOTTOMLEFT",546+dockshiftx,38+dockshifty);
		else
			AutoBar_Config[AutoBar_Player].display.docking = nil;
		end
	elseif (AutoBar_Config[AutoBar_Player].display.position) then
		AutoBar:SetPoint("CENTER","UIParent","BOTTOMLEFT",
		AutoBar_Config[AutoBar_Player].display.position.x,
		AutoBar_Config[AutoBar_Player].display.position.y);
	else
		AutoBar:SetPoint("CENTER","UIParent","CENTER",0,0);
	end
	local i, texture, counttxt, hotkey, fonttext, fontsize, fontoptions, percent;
	percent = buttonwidth / 36;
	if (percent > 1) then percent = 1; end
	for i = 1, AUTOBAR_MAXBUTTONS, 1 do
		local button = getglobal("AutoBar_Button"..i);
		if (i > (rows*columns)) then
			button:Hide();
			button.forcehidden = 1;
		else
			texture = getglobal("AutoBar_Button"..i.."NormalTexture");
			counttxt = getglobal("AutoBar_Button"..i.."Count");
			hotkey = getglobal("AutoBar_Button"..i.."HotKey");
			button.forcehidden = nil;
			button:SetAlpha(alpha);
			texture:SetAlpha(alpha);
			button:SetWidth(buttonwidth);
			texture:SetWidth(buttonwidth*1.833);
			button:SetHeight(buttonheight);
			texture:SetHeight(buttonheight*1.833);
			if (AutoBar_Config[AutoBar_Player].display.hidekeytext) then
				hotkey:Hide();
			else
				hotkey:Show();
				fonttext, fontsize, fontoptions = hotkey:GetFont();
				hotkey:SetFont(fonttext, 12*percent, fontoptions);
				hotkey:SetPoint("TOPLEFT","AutoBar_Button"..i,"TOPLEFT",-10,-2);
			end
			if (AutoBar_Config[AutoBar_Player].display.hidecount) then
				counttxt:Hide();
			else
				counttxt:Show();
				fonttext, fontsize, fontoptions = counttxt:GetFont();
				counttxt:SetFont(fonttext, 14*percent, fontoptions);
			end
			button:ClearAllPoints();
			if (i == 1) then
				button:SetPoint("TOPLEFT","AutoBar","TOPLEFT",0,0);
			elseif (columns == 1) then
				if (AutoBar_Config[AutoBar_Player].display.reversebuttons) then
					button:SetPoint("BOTTOM","AutoBar_Button"..(i-1),"TOP",0,gapping);
				else
					button:SetPoint("TOP","AutoBar_Button"..(i-1),"BOTTOM",0,gapping*-1);
				end
			elseif (math.mod(i,columns) == 1) then
				local row = math.floor(i/columns);
				if (AutoBar_Config[AutoBar_Player].display.reversebuttons) then
					button:SetPoint("BOTTOM","AutoBar_Button"..(i-columns),"TOP",0,gapping);
				else
					button:SetPoint("TOP","AutoBar_Button"..(i-columns),"BOTTOM",0,gapping*-1);
				end
			else
				if (AutoBar_Config[AutoBar_Player].display.reversebuttons) then
					button:SetPoint("RIGHT","AutoBar_Button"..(i-1),"LEFT",gapping*-1,0);
				else
					button:SetPoint("LEFT","AutoBar_Button"..(i-1),"RIGHT",gapping,0);
				end
			end
		end
	end
	AutoBar_AssignButtons();
	AutoBar_Button_UpdateButtons();
end

