local name, addon = ...

local playerID,guildID,db,options
local NUM_BAG_SLOTS = NUM_BAG_SLOTS
local GetContainerNumSlots = GetContainerNumSlots
local GetContainerItemLink = GetContainerItemLink
local GetContainerItemInfo = GetContainerItemInfo
local strsplit,format = strsplit,format
local sync = {}
local moduls = {}
local defaults = {
	['bagsToggle'] = true,
	['bankToggle'] = true,
	['charToggle'] = true,
	['bagsTooltip'] = true,
	['bankTooltip'] = true,
	['charTooltip'] = true,
	['showID'] = false,
	['icons'] = {},
	['names'] = {},
	['currencies'] = {},
	['bags'] = {},
	['bank'] = {},
	['guildbank'] = {},
	['units'] = {},
	['guilds'] = {},
	['CraftTipScale'] = 0.9
}
local L = LibStub("AceLocale-3.0"):GetLocale(name, true)
function addon:getPID()
	if(playerID) then
		return playerID
	end
	local pname, pserver = UnitFullName("player")
	if(not pserver) then
		return
	end
	local player = format("%s - %s",pname,pserver)
	playerID = 0
	local units = addon:GetNamespace('units')
	for k,v in pairs(units) do
		if(v['name']==player) then
			playerID = k
			return playerID
		end
		if(k>=playerID) then
			playerID = k
		end
	end
	playerID = playerID + 1
	units[playerID]= {
		['name'] = player,
		['faction'] = UnitFactionGroup('player')
	}
	return playerID
end
local function getChars()
	local chars = {}
	for k,v in pairs(db['units']) do
		chars[k] = v['name']
	end
	return chars
end
local function deleteChar()
	local cid = db['selectCID']
	if(cid and cid>0) then
		for k, modul in pairs(moduls) do
			modul:Delete(cid)
		end
		db['units'][cid] = nil
		if(cid == playerID) then
			playerID = nil
		end
	end
end
local function getGuilds()
	local guilds = {}
	for k,v in pairs(db['guilds']) do
		guilds[k] = v['name']
	end
	return guilds
end
local function deleteGuild()
	local gid = db['selectGID']
	if(gid and gid>0) then
		for k, modul in pairs(moduls) do
			modul:Delete(gid, 'guild')
		end
		db['guilds'][gid] = nil
		if(gid == guildID) then
			guildID = nil
		end
	end
end
function addon:getGID()
	local pname, pserver = UnitFullName("player")
	if(not pserver) then
		return
	end
	local guildName, guildRankName, guildRankIndex, guildRealm = GetGuildInfo("player")
	guildID = 0
	if(not guildName) then return end
	local guild = format("%s - %s",guildName,guildRealm and guildRealm or pserver)
	local guilds = addon:GetNamespace('guilds')
	for k,v in pairs(guilds) do
		if(v['name']==guild) then
			guildID = k
			return guildID
		end
		if(k>=guildID) then
			guildID = k
		end
	end
	guildID = guildID + 1
	guilds[guildID]= {
		['name'] = guild,
		['faction'] = UnitFactionGroup('player')
	}
	return guildID	
end
function addon:checkGID()
	if(not guildID) then
		guildID = addon:getGID()
	end
	if(guildID and guildID>0) then
		addon:GetNamespace('guildbank')
		return true
	end
end
function addon:getGuilds()
	return db['guilds']
end
local function setName(id,itemname)
	if(id and itemname) then
		local names = addon:GetNamespace('names')
		names[tonumber(id)] = itemname
	end
end
local function getId(itemName)
	for k,v in pairs(addon:GetNamespace('names')) do
		if(v==itemName) then
			return k
		end
	end
end
function addon:getName(id)
	local names = addon:GetNamespace('names')
	if(not names[tonumber(id)]) then
		setName(id,C_Item.GetItemNameByID(id))
	end
	return db['names'][id]
end
local function deleteNames()
	db['names'] = {}
end
function addon:setIcon(id,icon)
	if(id and icon) then
		local icons = addon:GetNamespace('icons')
		icons[tonumber(id)] = "|T"..icon..":0|t"
	end
end
function addon:getIcon(id)
	id = tonumber(id)
	if(id and not db['icons'][id]) then
		local itemName = C_Item.GetItemNameByID(id)
		local icon = C_Item.GetItemIconByID(id)
		setName(id,itemName)
		addon:setIcon(id,icon)
	end
	return db['icons'][id] or ''
end
local function deleteIcons()
	db['icons'] = {}
end
function addon:getUnits()
	return addon:GetNamespace('units')
end
local function search(id)
	local res = {}
	for k,modul in pairs(moduls) do
		if(type(modul.Search)=='function') then
			res = modul.Search(id,res)
		end
	end
	return res
end
function addon:GetModul(modName)
	for k,modul in pairs(moduls) do
		if(modul.name==modName) then
			return modul
		end
	end
end
local function output(b)
	local input, sum = {}, 0
	for k,modul in pairs(moduls) do
		if(type(modul.Output)=='function') then
			if(db[modul.name .. 'Tooltip']) then
				input,sum = modul.Output(input,sum,b)
			end
		end
	end
	return input,sum
end
local function specialoutput(tooltip, id)
	for k,modul in pairs(moduls) do
		if(type(modul.Search2)=='function' and db[modul.name .. 'Tooltip']) then
			local res = modul.Search2(id)
			if(res) then
				for k,v in pairs(res) do
					tooltip:AddLine(v)
				end
			end
		end
	end
end
local function checkID(itemID)
	if(C_TradeSkillUI and TradeSkillFrame ~= nil and TradeSkillFrame:IsVisible()) then
		local tab = GetMouseFocus()
		local par2 = tab:GetParent()
		local par = par2:GetParent()
		local tooltip = par2.tooltipFrame
		for i = 1, C_TradeSkillUI.GetRecipeNumReagents(par.selectedRecipeID) do
			if(tab.reagentIndex and i==tab.reagentIndex) then
				local recipeItemLink = C_TradeSkillUI.GetRecipeReagentItemLink(par.selectedRecipeID, i)
				itemID = addon:getItemId(recipeItemLink)
				break
			end
		end
		return tonumber(itemID),tooltip
	end
end
local curHooks,curTT,curID = {}
local function hookIt(self)
	self.zzTT = nil
end
function addon:setTT(id,tooltip)
	if(not tooltip.zzTT and not curHooks[tooltip]) then
		curHooks[tooltip] = true
		tooltip:HookScript("OnHide", hookIt)
	end
	tooltip.zzTT = true
	curTT = tooltip
	curID = id
end
function addon:getTT()
	return curID,curTT
end
local tmp = 0
local function GameTooltip_OnTooltipSetItem(tooltip)
	local _, link = tooltip:GetItem()
	if(not link) then
		return
	end
	local id = addon:getItemId(link)
	if(not id) then
		local tip
		id,tip = checkID(id)
		if(id and tip) then
			tooltip = tip
		end
	end
	if(id)then
		addon:setTT(id,tooltip)
		tooltip:AddLine()
		-- 加上總計
		local totalSum = 0
		for name,b in pairs(search(id)) do
			local dname, drealm = strsplit(" - ",name)
			local input,sum = output(b)
			if(sum>0) then
				tooltip:AddLine(format(L['tooltip_main_string'],addon:getIcon(id),dname,sum,addon:colorize(table.concat(input,', '),"ffffff")))
			end
			input = nil
			totalSum = totalSum + sum
		end
		tooltip:AddLine(L["Total: "]..totalSum)
		specialoutput(tooltip, id)
		if(db['showID']) then
			tooltip:AddLine(format(L['tooltip_id_string'],id))
		end
	end
	tooltip:Show()
end
function addon:updateTT()
	local id,tip = addon:getTT()
	if(tip and tip.zzTT) then
		if(id) then
			tip:SetItemByID(id)
		end
	end
end
GameTooltip:HookScript("OnTooltipSetItem", GameTooltip_OnTooltipSetItem)

-- 自行加入聊天視窗點物品連結的說明
ItemRefTooltip:HookScript("OnTooltipSetItem", GameTooltip_OnTooltipSetItem)

local craftTip = CreateFrame( "GameTooltip", name.."CraftReagentTip", nil, "GameTooltipTemplate")
local function CraftReagent_OnLeave(self,...)
	craftTip:Hide()
end
local function CraftReagent_OnEnter(self,...)
	if(self.hasItem==1) then
		local itemName = self['Name']:GetText()
		if(itemName) then
			local id = getId(itemName)
			craftTip:Hide()
			craftTip:ClearLines()
			craftTip:SetOwner(self, "ANCHOR_TOPLEFT")
			if(id) then
				craftTip:SetItemByID(id)
				GameTooltip_OnTooltipSetItem(craftTip)
			else
				craftTip:SetCraftItem(GetCraftSelectionIndex(), self:GetID())
			end
			craftTip:Show()
			CursorUpdate()
		end
	end
end

function addon:funcSync(func,delayed)
	local st = GetTime()
	if(delayed and sync[func]['times'][delayed]) then
		sync[func]['times'][delayed] = nil
	end
	sync[func] = sync[func] or {
		['last'] = 0,
		['times'] = {}
	}
	if(not (st == sync[func]['last'])) then
		sync[func]['last'] = st
		return true
	else
		if(not sync[func]['times'][st]) then
			sync[func]['times'][st] = true
			C_Timer.After(.1, function() func(st) end)
		end
		return
	end	
end
local events = {}
local ignItems = {}

local hookedCraft = {}
function events:CRAFT_SHOW(...)
	for i = 1, MAX_CRAFT_REAGENTS,1 do
		if(not hookedCraft["CraftReagent"..i]) then
			_G["CraftReagent"..i]:SetScript("OnEnter", CraftReagent_OnEnter)
			_G["CraftReagent"..i]:SetScript("OnLeave", CraftReagent_OnLeave)
			hookedCraft["CraftReagent"..i] = true
		end
	end
end
function events:GET_ITEM_INFO_RECEIVED(event, id)
	if(id and id>0) then
		if(ignItems[id]) then return end
		local itemName = C_Item.GetItemNameByID(id)
		if(itemName) then
			setName(id,itemName)
		else
			ignItems[id] = true
		end
	end
end
events.ITEM_DATA_LOAD_RESULT = events.GET_ITEM_INFO_RECEIVED
function events:TRADE_SKILL_LIST_UPDATE(event)
	addon:updateTT()
end
local function OnEvent(self, event, ...)
	if(type(events[event])=='function') then
		events[event](self,event,...)
	end
end
local function specialoutput2(id,res)
	for k,modul in pairs(moduls) do
		if(type(modul.Search2)=='function') then
			res = modul.Search2(id,res,true)
		end
	end
	return res
end
SlashCmdList[string.upper(name)] = function(msg)
	local um = string.upper(msg)
	for id, itemname in pairs(db['names']) do
		local un = string.upper(itemname)
		if(string.find(un,um)) then
			local item = Item:CreateFromItemID(id)
			local itemlink = item:GetItemLink()
			local dout = {}
			if(id)then
				-- 加上總計
				local totalSum = 0
				for name,b in pairs(search(id)) do
					local dname, drealm = strsplit(" - ",name)
					local input,sum = output(b)
					dout[#dout+1] = (format(L['cmd_main_string'],dname,sum,addon:colorize(table.concat(input,', '),"ffffff")))
					input = nil
					totalSum = totalSum + sum
				end
				dout[#dout+1] = L["Total: "]..totalSum
				dout = specialoutput2(id,dout)
			end
			if(#dout>0) then
				addon:Print(format(L['cmd_header_string'],addon:getIcon(id),itemlink and itemlink or itemname))
				for k,v in pairs(dout) do
					addon:Print(v)
				end
			end
		end
	end
end
_G["SLASH_"..string.upper(name).."1"] = "/find"
function addon:GetNamespace(namespace)
	if(namespace) then
		db[namespace] = db[namespace] or {}
		return db[namespace]
	end
end
-- 暫時修正
local skipClassic = {
	['void'] = addon:IsClassic(),
	['guildbank'] = addon:IsClassic(),
	['currency'] = addon:IsClassic()
}
function addon:RegisterModul(modul, namespace)
	moduls[#moduls+1] = modul
	if(not skipClassic[namespace]) then
		self:AddConfigEntry(name,"toggle",namespace.."Toggle",L[namespace],L['pref_modul_toggle'](L[namespace]),1,nil,nil,nil,nil,self['options']['args'][name]['args']["ModulGroup"])
		self:AddConfigEntry(name,"toggle",namespace.."Tooltip",L[namespace],L['pref_tooltip_toggle'](L[namespace]),1,nil,nil,nil,nil,self['options']['args'][name]['args']["ModulTooltip"])
	end
	return self:GetNamespace(namespace), db[namespace.."Toggle"]
end
function addon:GetPref(prefName)
	return db[prefName]
end
local function getPref(pref)
	return db[pref[#pref]]
end
local function setPref(pref,value)
	db[pref[#pref]] = value
	if(pref[#pref] == 'CraftTipScale') then
		craftTip:SetScale(value)
	else
		for k, modul in pairs(moduls) do
			if(modul.name .. 'Toggle' == pref[#pref]) then
				if(value) then
					if(type(modul.Enable)=='function') then
						modul:Enable()
					end
				else
					if(type(modul.Disable)=='function') then
						modul:Disable()
					end			
				end
			elseif(type(modul.setPref)=='function' and string.sub(pref[#pref],0,string.len(modul.name)) == modul.name) then
				modul.setPref(pref[#pref], value)
			end
		end
	end
end
local function init(self, ...)
	options = addon:InitConfig(name, true, {
		['type'] = "launcher",
		['icon'] ="Interface\\Icons\\INV_Misc_Bag_10_Blue",
	}, getPref, setPref)
	db = addon['db']['profile'][name]
	local list = {}
	local skipRetail = {
		['CRAFT_SHOW'] = true
	}
	for event,func in pairs(events) do
		if((addon:IsClassic() and not db['donthookCraftFrame']) or (not addon:IsClassic() and not skipRetail[event])) then
			list[#list+1] = event
		end
	end
	addon:RegisterFunc(list,"OnEvent", OnEvent)
	addon:AddConfigEntry(name,"group","ModulGroup",L['pref_modul_header'],L['pref_modul_desc'],1,true)
	addon:AddConfigEntry(name,"group","ModulTooltip",L['pref_tooltip_header'],L['pref_tooltip_desc'],1,true)
	addon:AddConfigEntry(name,"toggle","showID",L['pref_itemid_header'],L['pref_itemid_desc'],1)
	if(addon:IsClassic()) then
		if(not addon:GetPref("CraftTipScale")) then
			setPref({"CraftTipScale"},0.9)
		end
		craftTip:SetScale(addon:GetPref("CraftTipScale"))
		addon:AddConfigEntry(name,"group","CraftTip",L['pref_crafttip_header'],L['pref_crafttip_desc'],3,true)
		addon:AddConfigEntry(name,"toggle","donthookCraftFrame",L['pref_donthookCraftFrame_header'],L['pref_donthookCraftFrame_desc'],1,nil,nil,nil,nil,options['args'][name]['args']["CraftTip"])
		addon:AddConfigEntry(name, "range","CraftTipScale",L['pref_crafttipscale_header'],L['pref_crafttipscale_desc'],2,0.01,1,.01,false,options['args'][name]['args']["CraftTip"])
	end
	addon.dbmenu = addon:AddConfigMenu({
		['name'] = L['Database'],
		['childGroups'] = 'tab',
		['order'] = 20,
		['menuGet'] = getPref,
		['menuSet'] = setPref
	})
	addon.menuchar = addon:AddConfigMenu({
		['name'] = L['Character'],
		['order'] = 10,
		['menuGet'] = getPref,
		['menuSet'] = setPref
	},addon.dbmenu)
	addon:AddConfigEntry(name,"select","selectCID",L['pref_maint_char_header'],L['pref_maint_char_desc'],1,getChars,nil,nil,nil,addon.menuchar)
	addon:AddConfigEntry(name,"execute","deleteCID",L['pref_maint_char_del_header'],L['pref_maint_char_del_desc'],2,deleteChar,nil,nil,nil,addon.menuchar)
	addon.menuguild = addon:AddConfigMenu({
		['name'] = L['Guild'],
		['order'] = 20,
		['menuGet'] = getPref,
		['menuSet'] = setPref
	},addon.dbmenu)
	addon:AddConfigEntry(name,"select","selectGID",L['pref_maint_guild_header'],L['pref_maint_guild_desc'],1,getGuilds,nil,nil,nil,addon.menuguild)
	addon:AddConfigEntry(name,"execute","deleteGID",L['pref_maint_guild_del_header'],L['pref_maint_guild_del_desc'],2,deleteGuild,nil,nil,nil,addon.menuguild)
	addon:AddConfigEntry(name,"execute","deleteNames",L['pref_maint_names_del_header'],L['pref_maint_names_del_desc'],2,deleteNames,nil,nil,nil,addon.dbmenu)
	addon:AddConfigEntry(name,"execute","deleteIcons",L['pref_maint_icons_del_header'],L['pref_maint_icons_del_desc'],2,deleteIcons,nil,nil,nil,addon.dbmenu)
end
addon:startup(name, name, init, true, defaults)