if (not ItemDataCache) then ItemDataCache = {} end
local ItemDataCache=ItemDataCache

function ItemDataCache:OnLoad()
	this:RegisterEvent("VARIABLES_LOADED");
	this:RegisterEvent("PLAYER_ENTERING_WORLD");
	this:RegisterEvent("BAG_UPDATE");
	-- this:RegisterEvent("UNIT_INVENTORY_CHANGED")
	this:RegisterEvent("MERCHANT_SHOW");
	-- this:RegisterEvent("MERCHANT_UPDATE");
	-- this:RegisterEvent("PLAYER_LEAVING_WORLD")
end

function ItemDataCache:OnEvent(self, event)
	if (event == "VARIABLES_LOADED") then
		ItemDataCache.Init()
		ItemDataCache.PurgeLocalData("ByID_selltovendor")
		ItemDataCache.isLoaded = true
		return
	end
	if (event == "MERCHANT_SHOW") then
		ItemDataCache.ScanBagsAtMerchant()
		return
	end
	if (event == "PLAYER_ENTERING_WORLD") then
		ItemDataCache.InitLocalClassName(9, 3)
		ItemDataCache.InitLocalClassName(9, 6)
		ItemDataCache.InitLocalClassName(9, 8)
		ItemDataCacheTooltip:SetOwner(UIParent, "ANCHOR_NONE")
		return
	end
	if (event == "UNIT_INVENTORY_CHANGED") then
		return
	end
	if (event == "BAG_UPDATE") then
		-- For cases when you trade or equip/deequip with merchant window open
		ItemDataCache.ScanBagsAtMerchant()
		return
	end
	if (event == "PLAYER_LEAVING_WORLD") then
		-- this:UnregisterEvent("UNIT_INVENTORY_CHANGED");
		return
	end
end

function ItemDataCache.Init()
	ItemDataCacheTooltip:SetScript("OnTooltipAddMoney", ItemDataCache.OnTooltipAddMoney);
	if(not ItemDataCacheLocal) then ItemDataCacheLocal={} end
	-- if(not ItemDataCacheLocal.ByName_data) then ItemDataCacheLocal.ByName_data={} end
	if(not ItemDataCacheLocal.ByID_selltovendor) then ItemDataCacheLocal.ByID_selltovendor={} end
	if(not ItemDataCacheLocal.ByID_maxcharges) then ItemDataCacheLocal.ByID_maxcharges={} end
	ItemDataCache.OverrideInformant()
end

-- Removes data from local dynamic cache that is already present in static cache
-- /script ItemDataCache.PurgeLocalData("ByID_selltovendor")
function ItemDataCache.PurgeLocalData(localTable)
	local purged, updated = 0, 0
	local getStaticDataFunction=ItemDataCache.Get[localTable]
	local staticData
	for index, value in pairs(ItemDataCacheLocal[localTable]) do
		staticData=getStaticDataFunction(index, true)
		if(staticData) then
			if(value==staticData) then
				ItemDataCacheLocal[localTable][index]=nil
				purged=purged+1
			else
				updated=updated+1
			end
		end
	end
	ItemDataCache.Chatback("Finished local data purge for "..localTable..". "..purged.." entries matching static cache freed. "..updated.." entries with data more recent than static cache found.")
end

if(not ItemDataCache.Get) then ItemDataCache.Get={} end
if (not ItemDataCache.OnUpdate) then ItemDataCache.OnUpdate = {} end
function ItemDataCache.Get.ByID_maxcharges(itemID)
	return ItemDataCacheLocal and ItemDataCacheLocal.ByID_maxcharges and ItemDataCacheLocal.ByID_maxcharges[itemID]
end
function ItemDataCache.OnUpdate.ByID_maxcharges() end

function ItemDataCache.UpdateLocalDataByID(localTable, itemID, value)
	local _, itemLink=GetItemInfo(itemID)
	if(value==nil) then
		if(ItemDataCacheLocal[localTable][itemID]) then ItemDataCache.Chatback(format("Resetting local data for table %s item %s.", localTable, itemLink)) end
		ItemDataCacheLocal[localTable][itemID]=nil
		return
	end
	local knownData=ItemDataCache.Get[localTable](itemID)
	if(not knownData) then
		ItemDataCache.Chatback(format("Found new data for table %s item %s: %s.", localTable, itemLink, tostring(value)))
		ItemDataCacheLocal[localTable][itemID]=value
		ItemDataCache.OnUpdate[localTable]()
	elseif(knownData ~= value) then
		ItemDataCache.Chatback(format("Found UPDATED data for table %s item %s: %s.", localTable, itemLink, tostring(value)))
		-- ItemDataCache.Chatback("Static data: "..tostring(staticData)..", Local data: "..tostring(localCacheData)..".")
		ItemDataCacheLocal[localTable][itemID]=value
		ItemDataCache.OnUpdate[localTable]()
	end
end

local scaningID, scaningLink, scaningStack, scaningMoneyFound, scaningChargesFound, scaningDurabilityFound, scaningDurabilityMaxFound
function ItemDataCache.OnTooltipAddMoney(self, money)
	-- ItemDataCache.Chatback("Caught adding money. ID: "..scaningID.." StackSize: "..scaningStack.." Price: "..money.." PriceForOne: "..(money/scaningStack))
	scaningMoneyFound=money/scaningStack
end

-- /script ItemDataCache.ScanBagsAtMerchant()
function ItemDataCache.ScanBagsAtMerchant()
	-- ItemDataCache.Chatback("Scanning...")
	if((not MerchantFrame:IsVisible()) or InRepairMode()) then return end
	for bag=0,NUM_BAG_FRAMES do
		for slot=1,GetContainerNumSlots(bag) do
			scaningLink=GetContainerItemLink(bag, slot)
			if(scaningLink) then
				local _
				scaningID=tonumber(strmatch(scaningLink, ".*item:(%d+):.*"))
				_, scaningStack=GetContainerItemInfo(bag, slot)
				-- ItemDataCache.Chatback("Trying to scan "..scaningLink..".")
				ItemDataCacheTooltip:ClearLines();
				scaningMoneyFound=false
				scaningChargesFound=false
				scaningDurabilityFound=false
				scaningDurabilityMaxFound=false
	        	        ItemDataCacheTooltip:SetBagItem(bag, slot);
				-- Scan always to find items with charges (previously scaned only for "No sell price")
				ItemDataCache.ScanTooltip()
				if(scaningChargesFound) then
					ItemDataCache.InitLocalClassName(9, 3, false)
					ItemDataCache.InitLocalClassName(9, 6, false)
					ItemDataCache.InitLocalClassName(9, 8, false)
					local class, subClass=ItemDataCache.Get.ByID_class(scaningID)
					if((class and subClass) and ((class==9 and subClass==3) or (class==9 and subClass==6) or (class==9 and subClass==8))) then
						ItemDataCache.UpdateLocalDataByID("ByID_maxcharges", scaningID, nil)
					else
						ItemDataCache.UpdateLocalDataByID("ByID_maxcharges", scaningID, true)
					end
				end
				-- if(scaningChargesFound) then ItemDataCache.Chatback(scaningLink.." charges: "..tostring(scaningChargesFound)..".") end
				-- reset local price if item have charges
				if(ItemDataCache.Get.ByID_maxcharges(scaningID)) then
					ItemDataCache.UpdateLocalDataByID("ByID_selltovendor", scaningID, nil)
				-- Do not save price if item is damaged
				elseif(scaningDurabilityFound == scaningDurabilityMaxFound) then
					if(scaningMoneyFound) then ItemDataCache.UpdateLocalDataByID("ByID_selltovendor", scaningID, scaningMoneyFound) end
				end
			end
		end
	end
end

local patternItemSpellChargesP1=gsub(ITEM_SPELL_CHARGES_P1, "%%.-d", "(%%d+)")
local patternItemSpellCharges=gsub(ITEM_SPELL_CHARGES, "%%.-d", "(%%d+)")
local patternDurability=gsub(DURABILITY_TEMPLATE, "%%.-d", "(%%d+)")
function ItemDataCache.ScanTooltip()
	for i=2, ItemDataCacheTooltip:NumLines(), 1 do
		local line=getglobal("ItemDataCacheTooltipTextLeft"..i):GetText()
		if (line) then
			-- Do something with one tooltip line
			-- ItemDataCache.Chatback(line)
			-- Check for "No sell price"
			if(line==ITEM_UNSELLABLE) then
				ItemDataCache.UpdateLocalDataByID("ByID_selltovendor", scaningID, 0)
			end
			if(not scaningChargesFound) then scaningChargesFound=strmatch(line, patternItemSpellChargesP1) end
			if(not scaningChargesFound) then scaningChargesFound=strmatch(line, patternItemSpellCharges) end
			if(scaningChargesFound) then
				scaningChargesFound=tonumber(scaningChargesFound)
			end
			if(not (scaningDurabilityFound and scaningDurabilityMaxFound)) then scaningDurabilityFound, scaningDurabilityMaxFound=strmatch(line, patternDurability) end
			-- ItemDataCache.Chatback(scaningLink..": "..tostring(scaningDurabilityFound).."/"..tostring(scaningDurabilityMaxFound))
			if(scaningDurabilityFound and scaningDurabilityMaxFound) then
				scaningDurabilityFound=tonumber(scaningDurabilityFound)
				scaningDurabilityMaxFound=tonumber(scaningDurabilityMaxFound)
			end
		end
	end
end

function ItemDataCache.DebugScanTooltip()
	for i=2, ItemDataCacheTooltip:NumLines(), 1 do
		local line=getglobal("ItemDataCacheTooltipTextLeft"..i):GetText()
		if (line) then
			ItemDataCache.Chatback(line)
		end
	end
end

-- /script local _, itemLink=GetItemInfo("item:20752:0:0:0:0:0:0:0") DEFAULT_CHAT_FRAME:AddMessage(itemLink)
-- /script ItemDataCacheTooltip:SetHyperlink("item:20752:0:0:0:0:0:0:0") ItemDataCache.DebugScanTooltip()
-- /script ItemDataCache.Chatback(ItemDataCacheTooltip:NumLines())
-- /script ItemDataCache.Chatback(ItemDataCacheTooltip:GetText())
-- /script ItemDataCacheTooltip:ClearLines() ItemDataCacheTooltip:SetHyperlink("item:27635:0:0:0:0:0:0:0") ItemDataCache.Chatback(getglobal("ItemDataCacheTooltipTextLeft1"):GetText())
function ItemDataCache.Chatback(value)
	DEFAULT_CHAT_FRAME:AddMessage("<ItemDataCache> "..tostring(value))
end

-- ItemDataCache.Chatback(patternItemSpellChargesP1)
-- ItemDataCache.Chatback(patternItemSpellCharges)
-- ItemDataCache.Chatback(patternDurability)
