local addon = LibStub("AceAddon-3.0"):GetAddon("InstanceMaps")
local mod = addon:NewModule("Loot", "AceEvent-3.0", "AceTimer-3.0", "AceConsole-3.0")

local pt = LibStub("LibPeriodicTable-3.1")
local BB = LibStub("LibBabble-Boss-3.0")
local BBL = BB:GetLookupTable()
local BBR = BB:GetReverseLookupTable()
local BZ = LibStub("LibBabble-Zone-3.0")
local BZL = BZ:GetLookupTable()
local BZR = BZ:GetReverseLookupTable()

-- Added by Sharak@BigFoot
local L = LibStub("AceLocale-3.0"):GetLocale("InstanceMaps", true)

local boss, current_zone, viewer

local InstanceMaps_Loot_ScanTooltip
function mod:OnEnable()
	self:RegisterMessage("InstanceMaps_Notes_Click")
	self:RegisterMessage("InstanceMap_Show")
	self:RegisterMessage("InstanceMap_Hide", "HideViewer")

	InstanceMaps_Loot_ScanTooltip = CreateFrame("GameTooltip", "InstanceMaps_Loot_ScanTooltip", UIParent, "GameTooltipTemplate")
	InstanceMaps_Loot_ScanTooltip:SetOwner(UIParent, "ANCHOR_NONE")
end

local bosslist
function mod:InstanceMap_Show()
	self:HideViewer() -- it'll be an old boss's data
	
	--[[if not bosslist then
		bosslist = CreateFrame("Button", "InstanceMaps_BossListButton")
	end--]]
end

function mod:InstanceMaps_Notes_Click(event, title, zone, data)
	if not title then return end
	self:DisplayLoot(zone, title)
end

function mod:DisplayLoot(zone, title)
	local old_boss = boss
	boss = title
	current_zone = zone

	if boss == old_boss then
		-- close the viewer
		boss = nil
		return self:HideViewer()
	end
	
	self:UpdateViewer()
end

function mod:RefreshViewer(viewer)
	if not (boss and current_zone) then return end

	self.scanning = self.scanning + 1;
	if (self.scanning >= self.max_scan) then
		viewer:Clear()
		
		viewer:AddLine(BBL[boss])

		if pt("InstanceLoot." .. current_zone .. "." .. boss) then
			viewer:AddLine()
			viewer:AddLine(L["Normal drops"])
			self:AddSetTo(viewer, "InstanceLoot." .. current_zone .. "." .. boss)
		end
		if pt("InstanceLootHeroic." .. current_zone .. "." .. boss) then
			viewer:AddLine()
			viewer:AddLine(L["Heroic drops"])
			self:AddSetTo(viewer, "InstanceLootHeroic." .. current_zone .. "." .. boss)
		end

		--viewer:AddLine("Close"):Handler("OnLeftClick", hide_viewer)

		viewer:Size()
		viewer:SetPosition()
		viewer:Show()
	end
end

function mod:UpdateViewer()
	if not (boss and current_zone) then return end
	if not viewer then
		viewer = LibStub("LibSimpleFrame-1.0"):New("InstanceMaps_LootViewer", {
			position = {point="CENTER", x=0, y=0},
			lock = false,
			scale = 1,
			strata = "FULLSCREEN",
			fade = 1,
			opacity = 1,
			width = 250,
			border = {0.9, 0.82, 0, 1},
			background = {0, 0, 0, 1},
			min_height = 20,
		}, 1, WorldMapFrame)
		InstanceMaps_LootViewer:SetScript("OnUpdate", InstanceMaps_LootViewer_OnUpdate);
		InstanceMaps_LootViewer:SetToplevel(true);
		InstanceMaps_LootViewer:SetFrameLevel(9);
		local close = CreateFrame("Button", nil, viewer, "UIPanelCloseButton")
		close:SetPoint("TOPRIGHT", viewer)
		close:SetScript("OnClick", self.HideViewer)
	end

	-- haxxor
	if (current_zone == "Blackrock Spire") then
		if pt("InstanceLoot.Upper " .. current_zone .. "." .. boss) then
			current_zone = "Upper Blackrock Spire"
		elseif pt("InstanceLoot.Lower " .. current_zone .. "." .. boss) then
			current_zone = "Lower Blackrock Spire"
		end
	end
	-- end haxxor

	if not pt("InstanceLoot." .. current_zone .. "." .. boss) and not pt("InstanceLootHeroic." .. current_zone .. "." .. boss) then
		return self:HideViewer()
	end
	
	viewer:Clear()
	viewer:AddLine(BBL[boss]);
	viewer:AddLine("");
	viewer:AddLine(L["Scanning loot items..."])
	viewer:Size()
	viewer:SetPosition()
	viewer:Show()

	self.scanning = 0;
	self.max_scan = 0;

	if (pt("InstanceLoot." .. current_zone .. "." .. boss)) then
		self.max_scan = self.max_scan + 1;
		self:ScanItems(1, "InstanceLoot." .. current_zone .. "." .. boss, mod.RefreshViewer, self, viewer);
	end

	if (pt("InstanceLootHeroic." .. current_zone .. "." .. boss)) then
		self.max_scan = self.max_scan + 1;
		self:ScanItems(2, "InstanceLootHeroic." .. current_zone .. "." .. boss, mod.RefreshViewer, self, viewer);
	end
end

local sort_set
do
	local itemids, droprates = {}, {}
	local function by_droprate(a, b)
		return tonumber(droprates[a]) > tonumber(droprates[b])
	end
	function sort_set(set)
		for k,v in pairs(itemids) do itemids[k] = nil end
		for k,v in pairs(droprates) do droprates[k] = nil end
		for id, drop in pt:IterateSet(set) do
			droprates[id] = drop
			table.insert(itemids, id)
		end
		table.sort(itemids, by_droprate)
		return itemids, droprates
	end
end

function InstanceMaps_LootViewer_OnUpdate()
	if (not this.tida) then
		this.tida = 0;
	end

	this.tida = this.tida + arg1;
	if (this.tida > 0.2) then
		this.tida = 0;

		if (this.scan_func) then
			if (this.scan_func[1] and this.scan_func[1].scanItems and GetTime() - this.scan_func[1].start_time > 1) then
				this.scan_func[1].scanItems(unpack(this.scan_func[1].args));
			end
			if (this.scan_func[2] and this.scan_func[2].scanItems and GetTime() - this.scan_func[2].start_time > 1) then
				this.scan_func[2].scanItems(unpack(this.scan_func[2].args));
			end
		end
	end
end

function mod:ScanItems(type, set, fin_event, ...)
	local fin = true;

	if (not self.scan_time) then
		self.scan_time = GetTime();
	end

	if (GetTime() - self.scan_time < 3) then
		local itemids, droprates = sort_set(set)
		for i, id in ipairs(itemids) do
			local name, link, rarity, _,_,_,_,_,_, texture = GetItemInfo(id);
			if (not name or not texture) then
				fin = nil;
				InstanceMaps_Loot_ScanTooltip:SetOwner(UIParent, "ANCHOR_NONE")
				InstanceMaps_Loot_ScanTooltip:SetHyperlink("item:" .. id)
				InstanceMaps_Loot_ScanTooltip:Hide()
			end
		end
	end

	if (fin) then
		if (not InstanceMaps_LootViewer.scan_func) then
			InstanceMaps_LootViewer.scan_func = {};
		end

		InstanceMaps_LootViewer.scan_func[type] = nil;

		self.scan_time = nil;

		if (fin_event) then
			fin_event(...);
		end

	else
		if (not InstanceMaps_LootViewer.scan_func) then
			InstanceMaps_LootViewer.scan_func = {};
		end

		InstanceMaps_LootViewer.scan_func[type] = {};
		InstanceMaps_LootViewer.scan_func[type].scanItems = mod.ScanItems;
		InstanceMaps_LootViewer.scan_func[type].start_time = GetTime();
		InstanceMaps_LootViewer.scan_func[type].args = {self, type, set, fin_event, ...};
	end
end

function mod:AddSetTo(viewer, set)
	local itemids, droprates = sort_set(set)
	for i, id in ipairs(itemids) do
		local name, link, rarity, _,_,_,_,_,_, texture = GetItemInfo(id)
		local percentage = ("%.1f%%"):format(droprates[id] / 10)
		local line
		if link then
			local r, g, b = GetItemQualityColor(rarity)
			line = viewer:AddLine("|T"..texture..":12|t "..name, percentage):Color(r, g, b)
				:Handler("OnEnter", self.OnMouseEnter, link)
		else
			line = viewer:AddLine(L["Item#"]..id, percentage):Color(1, 0, 0)
				:Handler("OnEnter", self.OnUnknownEnter)
		end
		line:Handler("OnLeftClick", self.DropClick, id):Handler("OnLeave", self.OnMouseLeave)
	end
end

function mod:HideViewer()
	if viewer then
		boss = nil
		viewer:Hide()
	end
end

function mod.DropClick(_, id)
	local name, link, rarity, _,_,_,_,_,_, texture = GetItemInfo(id)
	if not name then
		InstanceMaps_Loot_ScanTooltip:SetOwner(UIParent, "ANCHOR_NONE")
		InstanceMaps_Loot_ScanTooltip:SetHyperlink("item:" .. id)
		InstanceMaps_Loot_ScanTooltip:Hide()
		mod:ScheduleTimer(mod.UpdateViewer, 1, mod)
		return
	end
	if IsControlKeyDown() then
		DressUpItemLink(link)
	elseif IsShiftKeyDown() then
		if not ChatFrameEditBox:IsVisible() then
			ChatFrameEditBox:Show()
		end
		ChatFrameEditBox:Insert(link)
	else
		ShowUIPanel(ItemRefTooltip)
		if not ItemRefTooltip:IsVisible() then
			ItemRefTooltip:SetOwner(UIParent, "ANCHOR_PRESERVE")
		end
		ItemRefTooltip:SetHyperlink(link)
	end
end

function mod.OnMouseEnter(_, link)
	--GameTooltip_SetDefaultAnchor(GameTooltip, this)
	WorldMapTooltip:SetOwner(viewer, "ANCHOR_BOTTOMLEFT", 0, viewer:GetHeight() - math.abs(viewer:GetTop() - GetMouseFocus():GetTop()))
	WorldMapTooltip:SetHyperlink(link)
end

function mod.OnUnknownEnter()
end

function mod.OnMouseLeave()
	WorldMapTooltip:Hide()
end

