------------------------------------------------------------------
--IIfA.lua
--v0.8 - Original Author: Vicster0
-- v1.x and 2.x - rewrites by ManaVortex & AssemblerManiac
-- v3.x - new features mainly by ManaVortex
--[[
	Collects inventory data for all characters on a single account including the shared bank and makes this information available
	on tooltips across the entire account providing the playerwith useful insight into their account wide inventory.
DISCLAIMER
	This Add-on is not created by, affiliated with or sponsored by ZeniMax Media Inc. or its affiliates. The Elder Scrolls® and related
	logos are registered trademarks or trademarks of ZeniMax Media Inc. in the United States and/or other countries. All rights reserved."
]]
------------------------------------------------------------------
if IIfA == nil then IIfA = {} end
--local IIfA = IIfA

IIfA.name 				= "Inventory Insight"
IIfA.version 			= "3.18"
IIfA.author 			= "AssemblerManiac & manavortex"
IIfA.defaultAlertSound 	= nil
IIfA.colorHandler 		= nil
IIfA.isGuildBankReady 	= false
IIfA.TooltipLink 		= nil
IIfA.CurrSceneName 		= "hud"
IIfA.bFilterOnSetName 	= false
IIfA.searchFilter 		= ""
IIfA.trackedHouses		= {}
IIfA.EMPTY_STRING		= ""

local LMP = LibStub("LibMediaProvider-1.0")
local BACKPACK = ZO_PlayerInventoryBackpack
local BANK = ZO_PlayerBankBackpack

local ITEMTOOLTIP = ZO_ItemToolTip
local POPUPTOOLTIP = ZO_PopupToolTip

local IIFA_COLOR_DEFAULT = ZO_ColorDef:New("3399FF")

local task 			= IIfA.task or LibStub("LibAsync"):Create("IIfA_DataCollection")
IIfA.task			= task

-- --------------------------------------------------------------
--	Global Variables and external functions
-- --------------------------------------------------------------

-- BAG_SUBSCRIBER_BANK handled special in the CollectAll function - do NOT add to this list
-- has to be in this list because it's checked for in more than a few places as "do I track"

IIfA.trackedBags = {
	[BAG_WORN] 				= true,
	[BAG_BACKPACK] 			= true,
	[BAG_BANK] 				= true,
	[BAG_SUBSCRIBER_BANK]	= true,
	[BAG_GUILDBANK] 		= true,
	[BAG_VIRTUAL] 			= true,
	[BAG_HOUSE_BANK_ONE] 	= true,
	[BAG_HOUSE_BANK_TWO] 	= true,
	[BAG_HOUSE_BANK_THREE]	= true,
	[BAG_HOUSE_BANK_FOUR] 	= true,
	[BAG_HOUSE_BANK_FIVE] 	= true,
	[BAG_HOUSE_BANK_SIX] 	= true,
	[BAG_HOUSE_BANK_SEVEN] 	= true,
	[BAG_HOUSE_BANK_EIGHT] 	= true,
	[BAG_HOUSE_BANK_NINE] 	= true,
	[BAG_HOUSE_BANK_TEN] 	= true,
}

IIfA.dropdownLocNames = {
	"All",
	"All Banks",
	"All Guild Banks",
	"All Characters",
	"All Account Owned",
	"Bank and Characters",
	"Bank and Current Character",
	"Bank and other characters",
	"Bank Only",
	"Craft Bag",
	"Housing Storage",
	"All Houses",
}

-- 7-26-16 AM - global func, not part of IIfA class, used in IIfA_OnLoad
function IIfA_SlashCommands(cmd)

	if (cmd == IIfA.EMPTY_STRING) then
    	d("[IIfA]:Please find the majority of options in the addon settings section of the menu under Inventory Insight.")
    	d(" ")
    	d("[IIfA]:Usage - ")
    	d("	/IIfA [options]")
    	d(" 	")
    	d("	Options")
    	d("		debug - Enables debug functionality for the IIfA addon.")
    	d("		run - Runs the IIfA data collector.")
		d("		color - Opens the color picker dialog to set tooltip text color.")
		d("		toggle - Show/Hide IIfA")
		return
	end

	if (cmd == "debug") then
		if (IIfA.data.bDebug) then
			d("[IIfA]:Debug[Off]")
			IIfA.data.bDebug = false
		else
			d("[IIfA]:Debug[On]")
			IIfA.data.bDebug = true
		end
		return
	end

	if (cmd == "run") then
		d("[IIfA]:Running collector...")
		IIfA:CollectAll(true)
		return
	end

	if (cmd == "color") then
		local in2ColorPickerOnMouseUp = _in2OptionsColorPicker:GetHandler("OnMouseUp")
		in2ColorPickerOnMouseUp(_in2OptionsColorPicker, nil, true)
		return
	end

	if cmd == "toggle" then
		IIfA:ToggleInventoryFrame()
	end
end

function IIfA:DebugOut(output, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
	if not IIfA.data.bDebug then return end
	if a10 then
		d(zo_strformat(output, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10))
	elseif a9 then
		d(zo_strformat(output, a1, a2, a3, a4, a5, a6, a7, a8, a9))
	elseif a8 then
		d(zo_strformat(output, a1, a2, a3, a4, a5, a6, a7, a8))
	elseif a7 then
		d(zo_strformat(output, a1, a2, a3, a4, a5, a6, a7))
	elseif a6 then
		d(zo_strformat(output, a1, a2, a3, a4, a5, a6))
	elseif a5 then
		d(zo_strformat(output, a1, a2, a3, a4, a5))
	elseif a4 then
		d(zo_strformat(output, a1, a2, a3, a4))
	elseif a3 then
		d(zo_strformat(output, a1, a2, a3))
	elseif a2 then
		d(zo_strformat(output, a1, a2))
	elseif a1 then
		d(zo_strformat(output, a1))
	elseif output then
		d(output)
	else
		d("\n")
	end
end

function IIfA:StatusAlert(message)
	if (IIfA.data.bDebug) then
		ZO_Alert(UI_ALERT_CATEGORY_ALERT, IIfA.defaultAlertSound, message)
	end
end

function IIfA:TextColorFixup(settings)
--	d("settings.TextColorsCraftBag = " .. settings.TextColorsCraftBag)
	if settings.TextColorsToon == nil then
		if settings.in2TextColors then
--			d("old = " .. settings.in2TextColors)
			self.colorHandlerToon = ZO_ColorDef:New(settings.in2TextColors)
			self.colorHandlerBank = ZO_ColorDef:New(settings.in2TextColors)
			self.colorHandlerGBank = ZO_ColorDef:New(settings.in2TextColors)
			self.colorHandlerHouse = ZO_ColorDef:New(settings.in2TextColors)
			self.colorHandlerHouseChest = ZO_ColorDef:New(settings.in2TextColors)
			self.colorHandlerCraftBag = ZO_ColorDef:New(settings.in2TextColors)
		else
--			d("Using default textcolors")
			self.colorHandlerToon = ZO_ColorDef:New(IIFA_COLOR_DEFAULT:ToHex())
			self.colorHandlerBank = ZO_ColorDef:New(IIFA_COLOR_DEFAULT:ToHex())
			self.colorHandlerGBank = ZO_ColorDef:New(IIFA_COLOR_DEFAULT:ToHex())
			self.colorHandlerHouse = ZO_ColorDef:New(IIFA_COLOR_DEFAULT:ToHex())
			self.colorHandlerHouseChest = ZO_ColorDef:New(IIFA_COLOR_DEFAULT:ToHex())
			self.colorHandlerCraftBag = ZO_ColorDef:New(IIFA_COLOR_DEFAULT:ToHex())
		end
		settings.TextColorsToon = self.colorHandlerToon:ToHex()
		settings.TextColorsBank = self.colorHandlerBank:ToHex()
		settings.TextColorsGBank = self.colorHandlerGBank:ToHex()
		settings.TextColorsHouse = self.colorHandlerHouse:ToHex()
		settings.TextColorsHouseChest = self.colorHandlerHouse:ToHex()
		settings.TextColorsCraftBag = self.colorHandlerCraftBag:ToHex()
		settings.in2TextColors = nil
	else
--		d("using saved textcolors")
		self.colorHandlerToon = ZO_ColorDef:New(settings.TextColorsToon)
		self.colorHandlerBank = ZO_ColorDef:New(settings.TextColorsBank)
		self.colorHandlerGBank = ZO_ColorDef:New(settings.TextColorsGBank)
		self.colorHandlerHouse = ZO_ColorDef:New(settings.TextColorsHouse)
		self.colorHandlerHouseChest = ZO_ColorDef:New(settings.TextColorsHouseChest)
		self.colorHandlerCraftBag = ZO_ColorDef:New(settings.TextColorsCraftBag)
	end
end


function IIfA_onLoad(eventCode, addOnName)
	if (addOnName ~= "IIfA") then
		return
	end

	local valDocked = true
	local valLocked = false
	local valMinimized = false
	local valLastX = 400
	local valLastY = 300
	local valHeight = 798
	local valWidth = 380

	-- initializing default values
	local defaultGlobal = {
		saveSettingsGlobally 	= true,
		bDebug 					= false,
		showItemCountOnRight 	= true,
		showItemStats			= false,
		b_collectHouses			= false,
		collectHouseData		= {},
		ignoredCharEquipment	= {},
		ignoredCharInventories	= {},
		frameSettings =
			{
			["bank"] =			{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["guildBank"] =  	{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["tradinghouse"] = 	{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["smithing"] = 		{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["store"] = 		{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["stables"] = 		{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["trade"] = 		{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["inventory"] = 	{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["hud"] =   		{ hidden = true,  docked = false,     locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["alchemy"] =   	{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth }
			},

		bCollectGuildBankData 			= false,
		in2DefaultInventoryFrameView 	= "All",
		in2AgedGuildBankDataWarning 	= true,
		in2TooltipsFont 				= "ZoFontGame",
		in2TooltipsFontSize 			= 16,
		ShowToolTipWhen 				= "Always",
		DBv3 							= {},
		dontFocusSearch					= false,
	}

	-- initializing default values
	local default = {
		showItemCountOnRight	= true,
		showItemStats			= false,

		frameSettings =
			{
			["bank"] =			{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["guildBank"] =  	{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["tradinghouse"] = 	{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["smithing"] = 		{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["store"] = 		{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["stables"] = 		{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["trade"] = 		{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["inventory"] = 	{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["hud"] =   		{ hidden = true, docked = false, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth },
			["alchemy"] =   	{ hidden = false, docked = valDocked, locked = valLocked, minimized = valMinimized, lastX = valLastX, lastY = valLastY, height = valHeight, width = valWidth }
			},

		bCollectGuildBankData = false,
		in2DefaultInventoryFrameView = "All",
		in2AgedGuildBankDataWarning = true,
		in2TooltipsFont = "ZoFontGame",
		in2TooltipsFontSize = 16,
	}

	IIfA.minWidth = 410
	-- prevent resizing by user to be larger than this
	IIFA_GUI:SetDimensionConstraints(IIfA.minWidth, 300, -1, 1400)

	-- Grab a couple static values that shouldn't change while it's running
	IIfA.HeaderHeight = IIFA_GUI_Header:GetHeight()
	IIfA.SearchHeight = IIFA_GUI_Search:GetHeight()

	IIFA_GUI_ListHolder.rowHeight = 52	-- trying to find optimal size for this, set it in one spot for easier adjusting
	IIFA_GUI_ListHolder:SetDrawLayer(0)	-- keep the scrollable dropdown ABOVE this one
										-- (otherwise scrollable dropdown is shown like it's above the list, but the mouse events end up going through to the list)

	IIfA.currentCharacterId = GetCurrentCharacterId()
	IIfA.currentAccount = GetDisplayName()

	IIfA.filterGroup = "All"
	IIfA.filterTypes = nil

	-- grabs data from backpack, and worn items when we first open the inventory
	-- ZO_PreHook(PLAYER_INVENTORY, "ApplyBackpackLayout", IIfA.OnFirstInventoryOpen)
	ZO_PreHook(BACKPACK_GUILD_BANK_LAYOUT_FRAGMENT, "ApplyBackpackLayout", IIfA.CollectGuildBank)

	-- ZO_PreHook(SHARED_INVENTORY, "GetOrCreateBagCache", function(self, bagId)
		-- d("SHARED_INVENTORY: GetOrCreateBagCache: " .. tostring(bagId))
	-- end)
	-- ZO_PreHook(SHARED_INVENTORY, "PerformFullUpdateOnBagCache", function(self, bagId)
		-- d("SHARED_INVENTORY: PerformFullUpdateOnBagCache: " .. tostring(bagId))
	-- end)


	-- http://esodata.uesp.net/100016/src/libraries/utility/zo_savedvars.lua.html#67


	IIfA.settings 	= ZO_SavedVars:NewCharacterIdSettings("IIfA_Settings", 1, nil, default)
	IIfA.data 		= ZO_SavedVars:NewAccountWide("IIfA_Data", 1, "Data", defaultGlobal)

	IIfA:RebuildHouseMenuDropdowns()

	--  nuke non-global positioning settings
	local ObjSettings = IIfA:GetSettings()
	if ObjSettings.in2InventoryFrameSceneSettings ~= nil then
		ObjSettings.in2InventoryFrameSceneSettings = nil
	end
	if ObjSettings.in2InventoryFrameScenes ~= nil then
		ObjSettings.in2InventoryFrameScenes = nil
	end
	if ObjSettings.valDocked ~= nil then
		ObjSettings.valDocked = nil
		ObjSettings.valLocked = nil
		ObjSettings.valMinimized = nil
		ObjSettings.valLastX = nil
		ObjSettings.valLastY = nil
		ObjSettings.valHeight = nil
		ObjSettings.valWidth = nil
		ObjSettings.valWideX = nil
	end

	if IIfA.settings.in2ToggleGuildBankDataCollection ~= nil then
		IIfA.settings.in2ToggleGuildBankDataCollection = nil
	end
	if IIfA.data.in2ToggleGuildBankDataCollection ~= nil then
		IIfA.data.bCollectGuildBankData = IIfA.data.in2ToggleGuildBankDataCollection
		IIfA.data.in2ToggleGuildBankDataCollection = nil
	end

	if IIfA.data.showToolTipOnIIFAOnly ~= nil then
		if IIfA.data.showToolTipWhen == nil then		-- safety test - this should be nil at this point, but ya never know
			if IIfA.data.showToolTipOnIIFAOnly then
				IIfA.data.showToolTipWhen = "IIfA"
			else
				IIfA.data.showToolTipWhen = "Always"
			end
		end
		IIfA.data.showToolTipOnIIFAOnly = nil
	else
		if IIfA.data.showToolTipWhen == nil then
			IIfA.data.showToolTipWhen = "Always"
		end
	end
	if ObjSettings.showToolTipOnIIFAOnly ~= nil then
		if ObjSettings.showToolTipWhen == nil then		-- safety test - this should be nil at this point, but ya never know
			if ObjSettings.showToolTipOnIIFAOnly then
				ObjSettings.showToolTipWhen = "IIfA"
			else
				ObjSettings.showToolTipWhen = "Always"
			end
		end
		ObjSettings.showToolTipOnIIFAOnly = nil
	else
		if ObjSettings.showToolTipWhen == nil then
			ObjSettings.showToolTipWhen = IIfA.data.showToolTipWhen
		end
	end

	if IIfA.data.showStyleInfo == nil then
		IIfA.data.showStyleInfo = true
	end
	if ObjSettings.showStyleInfo == nil then
		ObjSettings.showStyleInfo = IIfA.data.showStyleInfo
	end


	-- 2-9-17 AM - convert saved data names into proper language for this session
    local lang = GetCVar("language.2")
	if IIfA.data.lastLang == nil or IIfA.data.lastLang ~= lang then
		IIfA:RenameItems()
		IIfA.data.lastLang = lang
	end

	IIfA:SetupCharLookups()

	-- overwrite non-global tables if present

	IIfA.settings.accountCharacters = nil
	IIfA.settings.guildBanks = nil


	-- this MUST remain in this location, otherwise it's possible that CollectAll will remove ALL characters data from the list (because they haven't been converted)
	if IIfA.data.accountCharacters ~= nil then
		IIfA:ConvertNameToId()
		IIfA.data.accountCharacters = nil
	end

	if ObjSettings.bFilterOnSetNameToo == nil then
		ObjSettings.bFilterOnSetNameToo = false
		IIfA.data.bFilterOnSetNameToo = false
	end

        --Other addons: FCOItemSaver
	if ObjSettings.FCOISshowMarkerIcons == nil then
		ObjSettings.FCOISshowMarkerIcons = false
		IIfA.data.FCOISshowMarkerIcons = false
	end

	if IIfA.data.guildBanks == nil then
		IIfA.data.guildBanks = {}
		local i
		for i = 1, GetNumGuilds() do
			local id = GetGuildId(i)
			local guildName = GetGuildName(id)
			IIfA.data.guildBanks[guildName] = {bCollectData = true, lastCollected = GetDate() .. "@" .. GetFormattedTime(), items = 0}
		end
	end

	if ObjSettings.bInSeparateFrame == nil then
		ObjSettings.bInSeparateFrame = true
		IIfA.data.bInSeparateFrame = true
	end

	IIfA.bFilterOnSetName = ObjSettings.bFilterOnSetName
	if ObjSettings.bFilterOnSetName == nil then
		IIfA.bFilterOnSetName = false
		ObjSettings.bFilterOnSetName = false
	end

	IIFA_GUI_Header_Filter_Button0:SetState(BSTATE_PRESSED)
	IIfA.LastFilterControl = IIFA_GUI_Header_Filter_Button0

	-- save off anchors for the ListHolder
	local _, point, relTo, relPoint, offsX, offsY = IIFA_GUI_ListHolder:GetAnchor(0)
	IIFA_GUI_ListHolder.savedAnchor1 = {point, relTo, relPoint, offsX, offsY}

	_, point, relTo, relPoint, offsX, offsY = IIFA_GUI_ListHolder:GetAnchor(1)
	IIFA_GUI_ListHolder.savedAnchor2 = {point, relTo, relPoint, offsX, offsY}

	IIfA:TextColorFixup(IIfA:GetSettings())

	SLASH_COMMANDS["/ii"] = IIfA_SlashCommands
	IIfA:CreateSettingsWindow(IIfA.settings, default)

	IIFA_GUI_ListHolder_Counts:SetHidden(not IIfA:GetSettings().showItemStats)

	IIfA.CharCurrencyFrame:Initialize(IIfA.data)
	IIfA.CharBagFrame:Initialize(IIfA.data)

	IIfA:SetupBackpack()	-- setup the inventory frame
	IIfA:CreateTooltips()	-- setup the tooltip frames

	-- manavortex, Feb. 22 2018: drop dbv2 support
	if nil ~= IIfA.data.DBv2 then IIfA.data.DBv2 = nil end

	-- keep EU and US items apart
	local worldName = GetWorldName():gsub(" Megaserver", IIfA.EMPTY_STRING)
	IIfA.data[worldName] = IIfA.data[worldName] or {}
	if IIfA.data[worldName].DBv3 == nil then
		 IIfA.data[worldName].DBv3 = IIfA.data.DBv3
	end
	IIfA.data.DBv3 = nil
	IIfA.database = IIfA.data[worldName].DBv3

--	IIfA:ActionLayerInventoryUpdate()

	if not ObjSettings.frameSettings.hud.hidden then
		IIfA:ProcessSceneChange("hud", "showing", "shown")
	end

	IIfA:RegisterForEvents()
	IIfA:RegisterForSceneChanges() -- register for callbacks on scene statechanges using user preferences or defaults

	IIfA.ignoredCharEquipment = IIfA.ignoredCharEquipment or {}
	IIfA.ignoredCharInventories = IIfA.ignoredCharInventories or {}
	IIfA.trackedBags[BAG_WORN] 		= not IIfA:IsCharacterEquipIgnored()
	IIfA.trackedBags[BAG_BACKPACK] 	= not IIfA:IsCharacterInventoryIgnored()

	IIfA:CollectAll(true)
end

EVENT_MANAGER:RegisterForEvent("IIfALoaded", EVENT_ADD_ON_LOADED, IIfA_onLoad)

function IIfA:ScanCurrentCharacterAndBank()

	IIfA:ScanBank()
	IIfA:ScanCurrentCharacter()
	zo_callLater(function()
		IIfA:MakeBSI()
	end, 5000)
end

function IIfA:MakeBSI()
	local bs = {}
	local idx
	local itemKey, DBItem, locname, data
	local bagSlot, qty
	for itemKey, DBItem in pairs(IIfA.database) do
		if DBItem.locations then
			for locname, data in pairs(DBItem.locations) do
				if data.bagSlot ~= nil and type(data.bagSlot) ~= "table" then
					bagSlot = data.bagSlot
					data.bagSlot = {}
					data.bagSlot[bagSlot] = data.itemCount
					data.itemCount = nil
				end
				if ((data.bagID == BAG_BACKPACK or data.bagID == BAG_WORN) and locname == IIfA.currentCharacterId) or	-- only index items ON this character if they're in backpack
					(data.bagID ~= BAG_BACKPACK and data.bagID ~= BAG_WORN) then
					idx = data.bagID
					if idx == BAG_GUILDBANK then		-- replace idx with appropriate guild bank name instead of the ID for BAG_GUILDBANK (to differentiate guild banks)
						idx = locname
					end
					if bs[idx] == nil then
						bs[idx] = {}
					end
					if nil ~= idx and nil ~= data.bagSlot then
						for bagSlot, qty in pairs(data.bagSlot) do
							bs[idx][bagSlot] = itemKey
						end
					end
				end
			end
		end
	end
	IIfA.BagSlotInfo = bs
	return bs	-- return only used in IIfA:SaveBagSlotIndex when IIfA.BagSlotInfo is nil
end

--[[
for reference

GetCurrentCharacterId()
Returns: string id

GetNumCharacters()
Returns: integer numCharacters

GetCharacterInfo(luaindex index)
Returns: string name,
		[Gender|#Gender] gender,
		integer level,
		integer classId,
		integer raceId,
		[Alliance|#Alliance] alliance,
		string id,
		integer locationId
__________________
	--]]

function IIfA:SetupCharLookups()

	IIfA.CharIdToName = {}
	IIfA.CharNameToId= {}
	local charInfo = {}
	-- create transient pair of lookup arrays, CharIdToName and CharNameToId (for use with the dropdown and converting stored data char name to charid)
	for i=1, GetNumCharacters() do
		local charName, _, _, _, _, _, charId, _ = GetCharacterInfo(i)
		charName = charName:sub(1, charName:find("%^") - 1)
		IIfA.CharIdToName[charId] = charName
		IIfA.CharNameToId[charName] = charId
	end
end

function IIfA:ConvertNameToId()
	-- run list of dbv2 items, change names to ids
	-- ignore attributes, and anything that's in guild bank list
	-- remaining items are character names (or should be)
	-- if found in CharNameToId, convert it, otherwise erase whole entry (since it's an orphan)
	-- do same for settings
	local tbl = IIfA.data.DBv2
	if nil == tbl or {} == tbl then return end
	for itemLink, DBItem in pairs(IIfA.data.DBv2) do
		for itemDetailName, itemInfo in pairs(DBItem) do
			local bagID = itemInfo.locationType
			if bagID ~= nil then
				if bagID == BAG_BACKPACK or bagID == BAG_WORN then
					if IIfA.CharNameToId[itemDetailName] ~= nil then
	--					d("Swapping name to # -- " .. itemLink .. ", " )
						DBItem[IIfA.CharNameToId[itemDetailName] ] = DBItem[itemDetailName]
						DBItem[itemDetailName] = nil
					end
				end
			end
		end
	end
end

-- used for testing - wipes all craft bag data
function IIfA:clearvbag()
	for itemLink, DBItem in pairs(IIfA.database) do
		for locationName, locData in pairs(DBItem.locations) do
--			if locData.bagID ~= nil then
				if locData.bagID == BAG_VIRTUAL then
					locData = nil
					DBItem[locationName] = nil
				end
--			end
		end
	end
end