--
-- ZubanLib Library Functions
-- Author: Zuban (chumpnet@hotmail.com)
--

-- 
-- UI
--

ZubanLib.UI = ZubanLib.Object:New{};

-- action bar
ZubanLib.Action = ZubanLib.UI:New{
	BAG_VALUE = -2;
	NUM_SLOTS = 120;
};

-- paper doll
ZubanLib.Inventory = ZubanLib.UI:New{
	BAG_VALUE = -1;
	NUM_SLOTS = 18;
};
	
-- bags
ZubanLib.Container = ZubanLib.UI:New{};
	
-- spellbook
ZubanLib.Spell = ZubanLib.UI:New{};

--
-- Action functions
--

function ZubanLib.Action:ForEach(action)
	for slot = 1, ZubanLib.Action.NUM_SLOTS do
		action(slot);
	end
end

function ZubanLib.Action:ForEachSlotNameRank(action)
	local name, rank;
	
	self:ForEach(
		function(slot)
			name = nil;
			rank = nil;
			
			ZubanLibActionTip:SetOwner(ZubanLibActionTip, "ANCHOR_NONE");
			ZubanLibActionTip:SetAction(slot);
			name = getglobal(ZubanLibActionTip:GetName().."TextLeft1"):GetText();
			rank = getglobal(ZubanLibActionTip:GetName().."TextRight1"):GetText();
			ZubanLibActionTip:Hide();
						
			action(slot, name, rank);
		end
	);
end

function ZubanLib.Action:Find(match)
	self:ForEachSlotNameRank(
		function(slot, name, rank)
			if (match(slot, name, rank)) then
				return slot, name, rank;
			end
		end
	);
	
	return nil;
end

function ZubanLib.Action:FindByTexture(name)
	local count, text, texture;
	
	return self:Find(
		function(slot, name, rank)
			count = GetActionCount(slot);
			text = GetActionText(slot);
			texture = GetActionTexture(slot);
			
			if (count == 0 and text == nil and texture == name) then
				return true;
			else
				return false;
			end
		end
	);
end

-- [Obsolete]
function ZubanLib.Action:GoToPage(page)
	page = tonumber(page);
	
	if (page > 0) then
		if (CURRENT_ACTIONBAR_PAGE ~= page) then
			CURRENT_ACTIONBAR_PAGE = page;
			ChangeActionBarPage();
		end
	end
end

-- [Obsolete]
function ZubanLib.Action:FindSlotByName(name, rank)
	local textName, textRank;
	ZubanLibActionTip:SetOwner(WorldFrame,"ANCHOR_NONE");

	for slot = 1, ZubanLib.Action.NUM_SLOTS do
		ZubanLibActionTip:SetAction(slot);
		textName = ZubanLibActionTipTextLeft1:GetText();
		textRank = ZubanLibActionTipTextRight1:GetText();

		if (textName == name and (rank == nil or rank == "" or textRank == rank)) then
			return slot;
		end		
	end
	
	return nil;
end

-- [Obsolete]
function ZubanLib.Action:FindSlotBySubName(name, rank)
	local textName, textRank;
	ZubanLibActionTip:SetOwner(WorldFrame,"ANCHOR_NONE");

	for slot = 1, ZubanLib.Action.NUM_SLOTS do
		ZubanLibActionTip:SetAction(slot);
		textName = ZubanLibActionTipTextLeft1:GetText();
		textRank = ZubanLibActionTipTextRight1:GetText();

		if (textName == nil) then
			textName = "";
		end
		
		if (textRank == nil) then
			textRank = "";
		end
		
		if (string.find(textName, name) and (rank == nil or rank == "" or string.find(textRank, rank))) then
			return slot;
		end		
	end
	
	return nil;
end

function ZubanLib.Action:WriteActionBar(start, stop)
	if (start == nil) then
		start = 1;
	end
	
	if (stop == nil) then
		stop = ZubanLib.Action.NUM_SLOTS;
	end

	ZubanLibActionTip:SetOwner(WorldFrame,"ANCHOR_NONE");
	
	for slot = start, stop do
		local textName = ZubanLib.Action:GetActionSpellName(slot);
		
		if (textName == nil) then
			textName = "- empty -";
		end
		
		ZubanLib.IO.Combat:Write(slot..": "..textName);
	end
end

function ZubanLib.Action:GetActionSpellName(slot)
	ZubanLibActionTip:SetAction(slot);
	return ZubanLibActionTipTextLeft1:GetText();
end

-- [Obsolete]
function ZubanLib.Action:FindSlotByTexture(name)
	local count, text, texture;

	for slot = 1, ZubanLib.Action.NUM_SLOTS do
		count = GetActionCount(slot);
		text = GetActionText(slot);
		texture = GetActionTexture(slot);
		
		if (count == 0 and text == nil and texture == name) then
			return slot;
		end		
	end
	
	return nil;
end

--
-- Inventory functions
--

function ZubanLib.Inventory:FindSlotByName(name)
	local itemName;
	
	for slot = 1, ZubanLib.Inventory.NUM_SLOTS do
		itemName = GetInventoryItemName(slot);
		
		if(itemName == name) then
			return slot;
		end
	end
	
	return nil;
end

--
-- Container functions
--

function ZubanLib.Container:ForEach(action)
	local itemLink;
	local itemName;

	for bag = 0, NUM_BAG_FRAMES do
		for slot = 1, GetContainerNumSlots(bag) do
			action(bag, slot);
		end
	end
end

function ZubanLib.Container:Find(match)
	self:ForEach(
		function(bag, slot)
			if (match(bag, slot)) then
				return bag, slot;
			end
		end
	);
	
	return nil, nil;
end

function ZubanLib.Container:FindByLink(link)
	local itemLink;
	
	return self:Find(
		function(bag, slot)
			itemLink = GetContainerItemLink(bag, slot);
			return itemLink == link;
		end
	);
end

function ZubanLib.Container:FindByName(name)
	local itemLink;
	local itemName;
	
	return self:Find(
		function(bag, slot)
			itemLink = GetContainerItemLink(bag, slot);
			
			if (itemLink) then
				itemName = GetItemInfo(itemLink);
				return itemName == name;
			end
			
			return false;
		end
	);
end

function ZubanLib.Container:Count(match)
	local total = 0;
	local count;
	
	self:ForEach(
		function(bag, slot)
			if (match(bag, slot)) then
				_, count = GetContainerItemInfo(bag, slot);
				total = total + count;
			end
		end
	);
	
	return total;
end

function ZubanLib.Container:CountByLink(link)
	local itemLink;
	
	return self:Count(
		function(bag, count)
			itemLink = GetContainerItemLink(bag, slot);
			return itemLink == link;
		end
	);
end

function ZubanLib.Container:CountByName(name)
	local itemLink;
	
	return self:Count(
		function(bag, count)
			itemLink = GetContainerItemLink(bag, slot);
			
			if (itemLink) then
				itemName = GetItemInfo(itemLink);
				return itemName == name;
			end
			
			return false;
		end
	);
end

-- [Obsolete]
function ZubanLib.Container:FindBagSlotByLink(link)
	local name = GetItemInfo(link);
	return self:FindBagSlotByName(name);
end

-- [Obsolete]
function ZubanLib.Container:FindBagSlotByName(name)
	local itemLink;
	local itemName;

	for bag = 0, NUM_BAG_FRAMES do
		for slot = 1, GetContainerNumSlots(bag) do
			itemLink = GetContainerItemLink(bag, slot);

			if (itemLink) then
				itemName = GetItemInfo(itemLink);
				
				if (itemName == name) then
					return bag, slot;
				end
			end
		end
	end

	return nil, nil;
end

-- [Obsolete]
function ZubanLib.Container:FindBagSlotBySubName(name)
	local itemLink;

	for bag = 0, NUM_BAG_FRAMES do
		for slot = 1, GetContainerNumSlots(bag) do
			itemLink = GetContainerItemLink(bag, slot);

			if (itemLink) then
				if (itemLink ~= nil and string.find(itemLink, name)) then
					return bag, slot;
				end
			end
		end
	end

	return nil, nil;
end

-- [Obsolete]
function ZubanLib.Container:CountByLink(link)
	local name = GetItemInfo(link);
	return self:CountByName(name);
end

-- [Obsolete]
function ZubanLib.Container:CountByName(name)
	local total = 0;
	local itemLink;
	local itemName;
	local itemcount;
	
	for bag = 0, NUM_BAG_FRAMES do
		for slot = 1, GetContainerNumSlots(bag) do
			itemLink = GetContainerItemLink(bag, slot);

			if (itemLink ~= nil) then
				itemName = GetItemInfo(itemLink);

				if  (itemName == name) then
					_, itemcount = GetContainerItemInfo(bag, slot);
					total = total + itemcount;
				end
			end
		end
	end

	return total;
end

-- searches both the containers and the inventory
function ZubanLib:FindBagSlotByName(name)
	local slot = ZubanLib.Inventory:FindSlotByName(name);
	
	if (slot) then
		return ZubanLib.Inventory.BAG_VALUE, slot;
	else
		return ZubanLib.Container:FindSlotByName(name);
	end
end

function ZubanLib.Container:UseBagSlotByName(name)
	local bag, slot = ZubanLib.Container:FindBagSlotByName(name);
	
	if (bag ~= nil and slot ~= nil) then
		UseContainerItem(bag, slot);
	end
end

--
-- spellbook functions
--

function ZubanLib.Spell:ForEach(action)
	local numSkillLineTabs = GetNumSpellTabs();
	local tabName, texture, offset, numSpells;
	local skillLineTab;

	for i = 1, numSkillLineTabs do
		tabName, texture, offset, numSpells = GetSpellTabInfo(i);

		for id = offset + 1, offset + numSpells do
			action(id);
		end
	end
end

function ZubanLib.Spell:Find(match)
	self:ForEach(
		function(id)
			if (match(id)) then
				return id;
			end
		end
	);
	
	return nil;
end

function ZubanLib.Spell:FindByName(name, subName, bookType)
	local spellName, subSpellName;
	
	return self:Find(
		function(id)
			spellName, subSpellName = GetSpellName(id, bookType);
						
			if (spellName == name and (not subName or subName == subSpellName)) then
				return true;
			else
				return false;
			end
		end
	);
end

-- [Obsolete]
function ZubanLib.Spell:FindIDByName(name, subName, bookType)
	local numSkillLineTabs = GetNumSpellTabs();
	local tabName, texture, offset, numSpells;
	local skillLineTab;
	local spellName, subSpellName;

	if (not bookType) then
		bookType = BOOKTYPE_SPELL;
	end
	
	for i = 1, numSkillLineTabs do
		tabName, texture, offset, numSpells = GetSpellTabInfo(i);

		for id = offset + 1, offset + numSpells do
			spellName, subSpellName = GetSpellName(id, bookType);
			
			--ZubanLib.IO.Chat.Write(id.." "..spellName.." "..subSpellName.." "..name);
			
			if (spellName == name and (not subName or subName == subSpellName)) then
				return id;
			end
		end
	end
	
	return nil;
end

-- [Obsolete]
function ZubanLib.Spell:CastSpellByName(name, subName, bookType)
	if (not bookType) then
		bookType = BOOKTYPE_SPELL;
	end

	local id = ZubanLib.Spell:FindIDByName(name, subName, bookType);
	
	if (id) then
		return CastSpell(id, bookType); -- function is protected in 2.0
	end
end

-- [Obsolete]
function ZubanLib.Spell:CastSpellByName2(name, subName)
	if (subName == nil) then
		subName = "";
	end

	local spell = name.."("..subName..")";
	
	return CastSpellByName(spell); -- function is protected in 2.0
end
