-- Not documented yet, sorry. Not that it too hard to figure out what's going on there...

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

local itemClassSubclassKnown={
	[0]={[0]={117, 118, 159, 414, 422, 724, 733, 787, 858, 929, 954, 955, 1017, 1082, 1179, 1180, 1181, 1191, 1205, 1251, 1262, 1322, 1399, 1477, 1478, 1645, 1703, 1707, 1708, 1710, 1711, 1712, 1970, 2070, 2287, 2289, 2290, 2304, 2313, 2455, 2456, 2457, 2458, 2459, 2581, 2596, 2633, 2679, 2680, 2681, 2682, 2683, 2684, 2685, 2687, 2888, 2894, 3012, 3013, 3220, 3382, 3383, 3385, 3386, 3388, 3389, 3391, 3530, 3531, 3662, 3663, 3664, 3665, 3666, 3726, 3728, 3729, 3770, 3771, 3775, 3823, 3824, 3825, 3826, 3827, 3828, 3829, 3927, 3928, 4265, 4419, 4422, 4424, 4426, 4457, 4479, 4480, 4536, 4537, 4538, 4539, 4540, 4541, 4542, 4544, 4592, 4593, 4594, 4598, 4599, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, 4623, 4791, 5042, 5095, 5205, 5206, 5232, 5457, 5472, 5476, 5477, 5480, 5525, 5527, 5631, 5633, 5634, 5740, 5816, 5996, 5997, 6038, 6048, 6049, 6050, 6051, 6052, 6149, 6289, 6290, 6291, 6303, 6308, 6361, 6362, 6372, 6373, 6450, 6451, 6529, 6530, 6532, 6657, 6662, 6807, 6887, 6888, 6890, 6949, 7307, 7676, 8164, 8173, 8364, 8365, 8544, 8545, 8766, 8932, 8948, 8949, 8951, 8953, 8956, 8957, 9036, 9088, 9144, 9154, 9155, 9172, 9179, 9187, 9197, 9206, 9224, 9233, 9260, 9264, 9311, 9312, 9313, 9360, 9451, 10306, 10308, 10592, 11846, 12190, 12210, 12212, 12214, 12215, 12217, 12218, 12238, 12820, 13442, 13443, 13444, 13445, 13446, 13452, 13454, 13456, 13457, 13458, 13511, 13512, 13754, 13756, 13758, 13851, 13927, 13929, 13930, 14529, 14530, 15564, 16166, 16167, 16168, 16169, 16170, 16766, 17048, 17196, 17197, 17198, 17202, 17222, 17404, 18045, 18154, 18662, 19182, 20470, 20471, 20472, 20709, 20857, 21030, 21031, 21033, 21071, 21072, 21114, 21140, 21153, 21213, 21217, 21546, 21552, 21990, 21991, 22058, 22829, 23334, 23354, 23756, 24072, 24105, 25498, 27503, 27651, 27856, 28101, 28102, 28103, 28104, 28399, 30816}},
	[1]={[1]={21340, 21341, 21342, 21872, 22243, 22244}},
	[2]={[20]={6256, 6365, 6367, 12225}},
	[5]={[0]={2665, 4470, 4471, 4611, 5116, 5140, 5529, 6265, 6358, 6359, 6370, 6371, 6452, 6453, 6470, 6471, 7067, 7068, 7069, 7070, 7071, 7072, 7075, 7076, 7077, 7078, 7079, 7080, 7081, 7082, 7972, 8168, 9060, 9061, 10286, 11291, 12803, 12808, 13422, 13423, 15420, 17020, 17030, 17031, 17032, 17033, 17034, 17035, 17036, 17037, 17038, 18512, 22147, 22456, 22575, 23571}},
	[6]={[2]={2512, 2515, 3030, 9399, 11285, 18042, 28053}, [3]={2516, 2519, 3033, 3465, 5568, 8067, 8068, 8069, 10512, 10513, 11284, 11630, 15997, 28060}},
	[7]={[0]={723, 729, 730, 731, 732, 765, 769, 783, 785, 814, 1015, 1080, 1081, 1206, 1274, 1288, 1468, 1475, 2251, 2296, 2318, 2319, 2320, 2321, 2324, 2325, 2447, 2449, 2450, 2452, 2453, 2589, 2592, 2604, 2605, 2672, 2673, 2674, 2675, 2677, 2678, 2692, 2770, 2771, 2772, 2775, 2776, 2835, 2836, 2838, 2840, 2841, 2842, 2862, 2863, 2871, 2880, 2886, 2924, 2928, 2930, 2934, 2996, 2997, 3172, 3173, 3174, 3182, 3239, 3241, 3340, 3355, 3356, 3357, 3358, 3369, 3371, 3372, 3404, 3466, 3470, 3478, 3486, 3575, 3576, 3577, 3667, 3685, 3712, 3713, 3730, 3731, 3777, 3818, 3819, 3820, 3821, 3857, 3858, 3859, 3860, 4231, 4232, 4233, 4234, 4235, 4236, 4289, 4291, 4304, 4305, 4306, 4337, 4338, 4339, 4340, 4341, 4342, 4402, 4461, 4625, 4655, 5060, 5465, 5468, 5469, 5471, 5503, 5504, 5635, 5637, 5784, 5785, 5833, 6037, 6042, 6043, 6217, 6218, 6260, 6261, 6338, 6339, 6522, 6889, 6986, 7428, 7911, 7912, 7964, 7965, 7966, 7967, 7969, 7974, 8146, 8150, 8151, 8152, 8153, 8167, 8169, 8170, 8171, 8343, 8368, 8831, 8836, 8838, 8839, 8845, 8846, 8923, 8924, 8925, 9210, 9262, 10285, 10290, 10620, 10647, 10648, 10938, 10939, 10940, 10978, 10998, 11082, 11083, 11084, 11128, 11130, 11134, 11135, 11137, 11138, 11139, 11144, 11145, 11174, 11175, 11176, 11177, 11178, 11370, 11371, 12037, 12184, 12202, 12203, 12204, 12205, 12208, 12359, 12360, 12365, 12404, 12644, 12655, 12804, 12810, 12811, 13463, 13464, 13465, 13467, 13468, 14047, 14048, 14227, 14256, 14341, 14342, 14343, 14344, 15407, 15409, 15417, 15423, 16202, 16203, 16204, 16206, 16207, 17194, 18256, 18567, 19726, 20424, 20520, 20744, 20745, 20746, 20747, 20749, 20750, 20815, 20816, 20817, 20824, 20957, 20963, 21752, 21840, 21842, 21844, 21877, 21882, 21887, 22445, 22446, 22447, 22448, 22449, 22461, 22462, 22644, 22785, 23446, 23676, 24186, 25649, 25707, 25844, 27668, 27671, 27676, 30817}},
	[9]={[3]={4408, 4409, 4410, 4412, 4414, 4416, 4417, 6716, 7561, 7742, 10601, 10603, 10604, 10606, 10609, 13308, 13309, 13310, 13311, 16041, 16043, 16046, 16048, 16050, 17720, 18648, 18649, 18650, 18652, 18655, 18656, 18661}, [6]={2553, 2555, 3394, 3395, 3832, 5640, 5642, 6053, 6056, 6211, 9293, 9294, 9295, 9296, 9298, 9300, 9301, 12958, 13476, 13478, 13490, 13491, 13492, 13495, 13496, 13499, 13520, 14634, 21547}, [8]={6342, 6344, 6347, 6348, 6349, 6375, 6377, 11038, 11039, 11081, 11098, 11101, 11150, 11151, 11152, 11163, 11164, 11165, 11166, 11167, 11202, 11203, 11204, 11205, 11206, 11207, 11208, 11225, 16215, 16218, 16220, 16221, 16223, 16224, 16243, 16246, 16248, 16251, 16252, 16255, 20752, 20753, 20758, 22539}},
	[11]={[2]={2101, 5439, 7278, 7371, 8217, 11362}, [3]={2102, 5441, 7279, 7372, 8218}},
	[12]={[0]={915, 1075, 1083, 1260, 1261, 1524, 2466, 2713, 2797, 2799, 3616, 3637, 3639, 3917, 3919, 3922, 3923, 3924, 3925, 3926, 3960, 4016, 4105, 4278, 4469, 4533, 5413, 5440, 5463, 5493, 5505, 5519, 5544, 5570, 5675, 5808, 5809, 7741, 8392, 8703, 9308, 10418, 10593, 12060, 12431, 12433, 12435, 18706, 18780, 19698, 19699, 19700, 19701, 19702, 19703, 19704, 19705, 19706, 19710, 19711, 19712, 19713, 19714, 20404, 23984, 24246}},
}

local THROTTLE=5
local lastRefreshDone=GetTime()
local copyFrame
function ItemDataCache.RefreshItem(itemID)
	-- Hammering this request seems to confuse either server or client,
	-- so we don't do it more than one time per THROTTLE seconds
	if(GetTime()-lastRefreshDone < THROTTLE) then return nil end
	if(GetItemInfo(itemID)) then return true end	-- already known
	if(not copyFrame) then local fromFrame=getglobal("DressUpModel") copyFrame=CreateFrame(fromFrame:GetFrameType(), nil, UIParent) end
	-- ItemDataCache.Chatback("Refreshing "..itemID..".")
	copyFrame:TryOn(itemID)
	lastRefreshDone=GetTime()
	return true
end

local NEED_MATCHES_GT=2
function ItemDataCache.RefreshClass(classID, subclassID)
	if(GetTime()-lastRefreshDone < THROTTLE) then return end
	for idx = 1, NEED_MATCHES_GT+1 do
		local itemID=itemClassSubclassKnown[classID][subclassID][idx]
		local _, _, _, _, _, itemClass, itemSubclass=GetItemInfo(itemID)
		-- Must be careful with IDs in itemClassSubclassKnown.
		-- Incorrect IDs can cause disconnect there.
		if(not (itemClass and itemSubclass)) then
			ItemDataCache.RefreshItem(itemID)
			-- rotate items to get more chances
			table.insert(itemClassSubclassKnown[classID][subclassID], (table.remove(itemClassSubclassKnown[classID][subclassID], idx)))
			return
		end
	end
end

-- Try to init all known classes without refreshing
function ItemDataCache.InitLocalClassNameAll()
	for classID, subclassTable in pairs(itemClassSubclassKnown) do
		for subclassID in pairs(subclassTable) do
			ItemDataCache.InitLocalClassName(classID, subclassID, true)
		end
	end
	-- self-destruct
	ItemDataCache.InitLocalClassNameAll=nil
end

-- Called once in a while from some event to see if there are
-- any classes that are not refreshed/initialized yet
-- Self-destructs when all work is done
local function ItemDataCache_PassiveInitRefreshNextClass()
	if(GetTime()-lastRefreshDone < THROTTLE) then return end
	for classID, subclassTable in pairs(itemClassSubclassKnown) do
		for subclassID in pairs(subclassTable) do
			if(itemClassSubclassKnown[classID][subclassID]) then
				return ItemDataCache.InitLocalClassName(classID, subclassID)
			end
		end
	end
	-- if we have nothing more to do, self-destruct
	ItemDataCache_PassiveInitRefreshNextClass=nil
end

local itemClassName={}
local itemClassID={}
local itemSubclassName={}
local itemSubclassID={}
function ItemDataCache.InitLocalClassName(classID, subclassID, doNotRefresh)
	-- No samples
	if((not itemClassSubclassKnown[classID]) or (not itemClassSubclassKnown[classID][subclassID])) then return nil end
	-- Already initialized
	if(itemClassName[classID] and itemClassName[classID][subclassID]) then return true end

	local className, subclassName
	if(not itemClassSubclassKnown[classID][subclassID]) then return end
	local match=0
	-- TODO: better match detection. Table of hits, maybe?
	for idx, itemID in pairs(itemClassSubclassKnown[classID][subclassID]) do
		local _, _, _, _, _, itemClass, itemSubclass=GetItemInfo(itemID)
		if(itemClass==nil or itemSubclass==nil) then
			-- Do nothing
		elseif(className==nil) then
			className=itemClass subclassName=itemSubclass match=match+1
		elseif(className==itemClass and subclassName==itemSubclass) then
			match=match+1
			if(match > NEED_MATCHES_GT) then break end
		end
	end
	if(match > NEED_MATCHES_GT) then
		if(not itemSubclassName[classID]) then itemSubclassName[classID]={} end
		if(not itemSubclassID[className]) then itemSubclassID[className]={} end
		itemClassName[classID]=className
		itemClassID[className]=classID
		itemSubclassName[classID][subclassID]=subclassName
		itemSubclassID[className][subclassName]=subclassID

		-- also save persistent cache
		local locale=GetLocale()
		if(not ItemDataCacheLocal.ClassSubclassRelations[locale]) then ItemDataCacheLocal.ClassSubclassRelations[locale]={} end
		if(not ItemDataCacheLocal.ClassSubclassRelations[locale].ItemClassID) then ItemDataCacheLocal.ClassSubclassRelations[locale].ItemClassID={} end
		if(not ItemDataCacheLocal.ClassSubclassRelations[locale].ItemSubclassID) then ItemDataCacheLocal.ClassSubclassRelations[locale].ItemSubclassID={} end
		if(not ItemDataCacheLocal.ClassSubclassRelations[locale].ItemSubclassID[className]) then ItemDataCacheLocal.ClassSubclassRelations[locale].ItemSubclassID[className]={} end
		if(not ItemDataCacheLocal.ClassSubclassRelations[locale].ItemClassName) then ItemDataCacheLocal.ClassSubclassRelations[locale].ItemClassName={} end
		if(not ItemDataCacheLocal.ClassSubclassRelations[locale].ItemSubclassName) then ItemDataCacheLocal.ClassSubclassRelations[locale].ItemSubclassName={} end
		if(not ItemDataCacheLocal.ClassSubclassRelations[locale].ItemSubclassName[classID]) then ItemDataCacheLocal.ClassSubclassRelations[locale].ItemSubclassName[classID]={} end
		ItemDataCacheLocal.ClassSubclassRelations[locale].ItemClassID[className]=classID
		ItemDataCacheLocal.ClassSubclassRelations[locale].ItemSubclassID[className][subclassName]=subclassID
		ItemDataCacheLocal.ClassSubclassRelations[locale].ItemClassName[classID]=className
		ItemDataCacheLocal.ClassSubclassRelations[locale].ItemSubclassName[classID][subclassID]=subclassName

		-- wipe table - we no longer need it
		itemClassSubclassKnown[classID][subclassID]=nil
		-- Initialized successfully
		return true
	else
		if(not doNotRefresh) then ItemDataCache.RefreshClass(classID, subclassID) end
		-- Failed, try again later
		return false
	end
end

function ItemDataCache.GetClassSubclassID(className, subclassName)
	-- Previously was located in event handler. Placing it there insures that no potentially dangerous
	-- refreshes happen if GetClass* functionality is not used.
	if(ItemDataCache_PassiveInitRefreshNextClass) then ItemDataCache_PassiveInitRefreshNextClass() end
	-- ItemDataCache_PassiveInitRefreshNextItem()
	local subclassTable=itemSubclassID[className]
	local classID=itemClassID[className]
	local subclassID=(subclassTable and subclassTable[subclassName] or nil)
	if((not classID) or (not subclassID)) then
		-- try cache
		local relationsTable=ItemDataCacheLocal.ClassSubclassRelations[GetLocale()]
		classID=relationsTable and relationsTable.ItemClassID
		classID=classID and classID[className]
		subclassID=relationsTable and relationsTable.ItemSubclassID
		subclassID=subclassID and subclassID[className]
		subclassID=subclassID and subclassID[subclassName]
	end
	return classID, subclassID
end

function ItemDataCache.GetClassSubclassName(classID, subclassID)
	-- Previously was located in event handler. Placing it there insures that no potentially dangerous
	-- refreshes happen if GetClass* functionality is not used.
	if(ItemDataCache_PassiveInitRefreshNextClass) then ItemDataCache_PassiveInitRefreshNextClass() end
	local subclassTable=itemSubclassName[classID]
	local className=itemClassName[classID]
	local subclassName=(subclassTable and subclassTable[subclassID] or nil)
	if((not className) or (not subclassName)) then
		-- try cache
		local relationsTable=ItemDataCacheLocal.ClassSubclassRelations[GetLocale()]
		className=relationsTable and relationsTable.ItemClassName
		className=className and className[classID]
		subclassName=relationsTable and relationsTable.ItemSubclassName
		subclassName=subclassName and subclassName[classID]
		subclassName=subclassName and subclassName[subclassID]
	end
	return className, subclassName
end

function ItemDataCache.Get.ByID_class(itemID)
	local _, _, _, _, _, itemClass, itemSubclass=GetItemInfo(itemID)
	return ItemDataCache.GetClassSubclassID(itemClass, itemSubclass)
end
