BlueItemInfo2 = CreateFrame("Frame")
BlueItemInfo2:SetScript("OnEvent", function(self, event, ...) self[event](self, ...) end)

local ItemTooltip = LibStub("LibItemTooltip-1.0")
local DropMenu = LibStub("LibDropMenu-1.0")

local f = strsub(UnitFactionGroup("player"), 1, 1)
local cache = {}
local N_cache = {}
local enchantCache = {}
local _G = getfenv(0)
local testFarmItem = nil

if not BluePrint then function BluePrint() end end

BINDING_HEADER_BLUEITEMINFO2 = "Blue Item Info 2"
BINDING_NAME_BLUEITEMINFO2_TOGGLE = "GUI창 열기/닫기"

local _G = _G
local type = _G.type
local abs = _G.abs
local select = _G.select
local strfind = _G.string.find
local strmatch = _G.string.match
local tonumber = _G.tonumber
local select = _G.select
local tinsert = _G.table.insert
local gsub = _G.gsub
local strsplit = _G.strsplit
local format = _G.format
local UnitName = _G.UnitName
local GetAddOnMetadata = _G.GetAddOnMetadata
local GetBuildInfo = _G.GetBuildInfo
local GetItemInfo = _G.GetItemInfo
local GetItemIcon = _G.GetItemIcon
local GetItemQualityColor = _G.GetItemQualityColor
local GetSpellInfo = _G.GetSpellInfo
local GetSpellLink = _G.GetSpellLink

BlueItemInfo2.title = "BlueItemInfo2"
BlueItemInfo2.version = GetAddOnMetadata("BlueItemInfo2", "Version")
BlueItemInfo2.website = GetAddOnMetadata("BlueItemInfo2", "X-Website")
BlueItemInfo2.icon = "Interface\\AddOns\\BlueItemInfo2\\Texture\\Icon"
BlueItemInfo2.data = { initDB = false, items = {}, num = 0, itemframes = 0, nver = nil, cver = GetBuildInfo(), virtual = false }
BlueItemInfo2.defalutCode = "200"

SLASH_BLUEITEMINFO1 = "/bii"
SLASH_BLUEITEMINFO2 = "/blueiteminfo"
SLASH_BLUEITEMINFO3 = "/아이템인포"

SlashCmdList["BLUEITEMINFO"] = function() BlueItemInfo2:OnClick() end

local init, pewinit

function BlueItemInfo2:OnInit()
	if init then return end
	init = true
	self.data.nver = self.data.nver or self.data.cver
	if testFarmItem then
		if UnitName("player") == "무서운독감" and GetRealmName() == "알렉스트라자" then
			if self.CreateFarmItemTable then
				self:CreateFarmItemTable(testFarmItem)
			end
		else
			testFarmItem = nil
		end
	end
end

function BlueItemInfo2:PLAYER_ENTERING_WORLD()
	if pewinit then return end
	if not init then
		self:OnInit()
	end
	pewinit = true
	self:UnregisterEvent("PLAYER_ENTERING_WORLD")
	if BlueItemInfo2DB and BlueItemInfo2DB.profiles then
		BlueItemInfo2DB = nil
	end
	BlueItemInfo2DB = BlueItemInfo2DB or {
		info = true, id = false, level = false, sort = true, esc = true, pos = { "CENTER", 0, 0 }, height = 279, scale = 1.0,
		category = "200", backdrop = { 0, 0, 0.24, 0.8 }, memo = {},
		minimapButton = { show = true, dragable = true, angle = 183, radius = 80, rounding = 10 },
	}
	if BlueItemInfo2Char == nil then
		BlueItemInfo2Char = { favorite = { {}, {}, {}, {}, {} } }
	elseif BlueItemInfo2Char.global then
		BlueItemInfo2Char = BlueItemInfo2Char.global
		if BlueItemInfo2Char == nil then
			BlueItemInfo2Char = { favorite = { {}, {}, {}, {}, {} } }
		else
			if BlueItemInfo2Char.favorite == nil then
				BlueItemInfo2Char.favorite = { {}, {}, {}, {}, {} }
			else
				for i = 1, 5 do
					if type(BlueItemInfo2Char.favorite[i]) ~= "table" then
						BlueItemInfo2Char.favorite[i] = {}
					end
				end
			end
		end
	end
	BlueItemInfo2Char = BlueItemInfo2Char or { favorite = { {}, {}, {}, {}, {} } }
	self.data.itemDB0 = self.data.itemDB0 or {}
	self.data.itemDB1 = self.data.itemDB1 or {}
	self:InitFavorite()
	self:InitMemo()
	ItemTooltip:Register(self, "ProcessTooltip")
	self.ScheduleEventDB = {}
	self.timer = 0
	self.isTemp = true
	self:SetScript("OnUpdate", self.OnUpdate)
	if BlueItemInfo2.CreateMinimapButton then
		BlueItemInfo2:CreateMinimapButton()
	end
end

function BlueItemInfo2:OnUpdate()
	self.timer = GetTime()
	self.isTemp = true
	for p, v in pairs(self.ScheduleEventDB) do
		if v[1] <= self.timer then
			if type(v[3]) == "function" then
				v[3](unpack(v[4]))
			elseif type(v[3]) == "string" and v[2] and v[2][v[3]] then
				v[2][v[3]](v[2], unpack(v[4]))
			end
			self.ScheduleEventDB[p] = nil
		else
			self.isTemp = nil
		end
	end
	if self.isTemp then
		self:SetScript("OnUpdate", nil)
	end
end

function BlueItemInfo2:ScheduleEvent(eventName, method, delay, owner, ...)
	if self:GetScript("OnUpdate") == nil then
		self:SetScript("OnUpdate", self.OnUpdate)
	end
	self.ScheduleEventDB[eventName] = { GetTime() + (delay or 0), owner or self, method, { ... } }
end

function BlueItemInfo2:CancelScheduledEvent(eventName)
	self.ScheduleEventDB[eventName] = nil
end

function BlueItemInfo2:OnClick()
	BlueItemInfo2:CloseDropMenu()
	if self.data.initDB then
		if self.GUI:IsVisible() then
			self.GUI:Hide()
		else
			self.GUI:Show()
		end
	else
		self:CreateItemTable()
		if self.CreateFavoriteItemTable then
			self:CreateFavoriteItemTable()
		end
		if self.CreateFarmItemTable then
			self:CreateFarmItemTable()
		end
		self:CreateCategory()
		self:CreateGUI()
		collectgarbage()
		self.data.initDB = true
	end
end

local itemID, enchantID, itemLevel, text, codes, old, itemName, n, c, s, t, p, sn, t, sz, ql, qn, oid, otext, oname, itemName, itemLink, itemRarity, itemTexture, item, f, itemType, itemCode, db, name

function BlueItemInfo2:ProcessTooltip(tooltip, name, link, id)
	if id then
		itemLevel = select(4, GetItemInfo(link))
		if BlueItemInfo2DB.info then
			text = self:GetItemText(id)
			for i = 1, #(text) do
				tooltip:AddLine(text[i].."|r")
			end
		end
		if BlueItemInfo2DB.memo[id] then
			tooltip:AddLine("|cff64cd3c▷|cffeaeaea"..BlueItemInfo2DB.memo[itemID].."|r")
		end
		if BlueItemInfo2DB.id and BlueItemInfo2DB.level and itemLevel then
			tooltip:AddDoubleLine("아이템ID: "..id, "아이템LV: "..itemLevel)
		elseif BlueItemInfo2DB.id then
			tooltip:AddLine("아이템ID: "..id)
		elseif BlueItemInfo2DB.level and itemLevel then
			tooltip:AddLine("아이템LV: "..itemLevel)
		end
	end
end

local swich = {
	["cN"] = "|cff64cd3c▶|cffffffa4",
	["cH"] = "|cff7df4b2",
	["cW"] = "|cffffffff",
	["cR"] = "|cffff7db4",
	["cI"] = "|cffdcdcdc",
	["cA"] = "|cff46aa46투기장 ",
	["cO"] = "|cff50cbff명예 ",
	["cQ"] = "|cff76eec6▷",
	["cF"] = "|cfffdcd8c",
	["cT"] = "|cff1ea4ff",
	["AV"] = "|cffdcdcdc알터랙 계곡 명예 훈장(",
	["ES"] = "|cffdcdcdc폭풍의 눈 명예 훈장(",
	["AB"] = "|cffdcdcdc아라시 분지 명예 훈장(",
	["WG"] = "|cffdcdcdc전쟁노래 협곡 명예 훈장(",
}

local reputation = {
	["-3"] = ": 매우 적대적 평판 필요",
	["-2"] = ": 적대적 평판 필요",
	["-1"] = ": 약간 적대적 평판 필요",
	["0"] = ": 중립적 평판 필요",
	["1"] = ": 약간 우호적 평판 필요",
	["2"] = ": 우호적 평판 필요",
	["3"] = ": 매우 우호적 평판 필요",
	["4"] = ": 확고한 동맹 평판 필요",
}

function BlueItemInfo2:GetItemText(id)
	if cache[id] then
		return cache[id]
	end
	local codes = self:GetItemValue(id)
	local text, old, itemName, n, c, s, t, p, sn, t, sz, ql, qn, oid, otext, oname = {}, {}
	for i = 1, #(codes) do
		if codes[i][1] == "D" or codes[i][1] == "B" then
			n = self:GetCategoryName(codes[i][2])
			if n then
				if old[2] == n[2] then
					old[3] = old[3]..", "..n[3]
					text[old[1]] = "cN"..n[2].." cW"..old[3]
				elseif old[3] == n[3] then
					old[2] = old[2]..", "..n[2]
					text[old[1]] = "cN"..old[2].." cW"..n[3]
				else
					tinsert(text, "cN"..n[2].." cW"..n[3])
					old = { #(text), n[2], n[3] }
				end
			end
		elseif codes[i][1] == "H" then
			n = self:GetCategoryName(codes[i][2])
			tinsert(text, format("cNcH%s(영웅) cW%s", n[2], n[3]))
		elseif codes[i][1] == "R" then
			n = self:GetCategoryName(codes[i][2])
			if old[2] == n[2] then
				old[3] = old[3]..", "..n[3]
				text[old[1]] = "cNcR"..n[2].." cW"..old[3]
			elseif old[3] == n[3] then
				old[2] = old[2]..", "..n[2]
				text[old[1]] = "cNcR"..old[2].." cW"..n[3]
			else
				tinsert(text, "cNcR"..n[2].." cW"..n[3])
				old = { #(text), n[2], n[3] }
			end
		elseif codes[i][1] == "r" then
			n = self:GetCategoryName(codes[i][2])
			if old[2] == n[2] then
				old[3] = old[3]..", "..n[3]
				text[old[1]] = "cNcR"..n[2].."(영웅) cW"..old[3]
			elseif old[3] == n[3] then
				old[2] = old[2]..", "..n[2]
				text[old[1]] = "cNcR"..old[2].."(영웅) cW"..n[3]
			else
				tinsert(text, "cNcR"..n[2].."(영웅) cW"..n[3])
				old = { #(text), n[2], n[3] }
			end
		elseif codes[i][1] == "A" then
			c, s, p = strsplit("@", codes[i][2])
			n = self:GetCategoryName(c)
			sn = strmatch(n[2] or "*", "시즌 (%d+)")
			t = "cNcA"..s.."점"
			if p then
				t = t..", cI개인평점 "..p.."점"
			end
			if sn then
				tinsert(text, t..", cW시즌 "..sn)
			else
				tinsert(text, t)
			end
		elseif codes[i][1] == "O" then
			c, s, t, p = strsplit("@", codes[i][2])
			n = self:GetCategoryName(c) or {}
			if t and p then
				tinsert(text, "cNcO"..s.."점 cW"..t.."), cI개인평점 "..p.."점")
			elseif t then
				tinsert(text, "cNcO"..s.."점 cW"..t..")")
			else
				tinsert(text, "cNcO"..s.."점")
			end
		elseif codes[i][1] == "F" then
			c, s, t, p = strsplit("@", codes[i][2])
			s = s ~= "" and s or nil
			t = t ~= "" and t or nil
			if s and t then
				if p then
					tinsert(text, format("cNcO%s점, cA%s점, cI개인평점 %s점 cW(겨울손아귀 호수)", s, t, p))
				else
					tinsert(text, format("cNcO%s점, cA%s점 cW(겨울손아귀 호수)", s, t))
				end
			elseif s then
				if p then
					tinsert(text, format("cNcO%s점, cI개인평점 %s점 cW(겨울손아귀 호수)", s, p))
				else
					tinsert(text, format("cNcO%s점 cW(겨울손아귀 호수)", s, p))
				end
			elseif t then
				if p then
					tinsert(text, format("cNcA%s점, cI개인평점 %s점 cW(겨울손아귀 호수)", s, p))
				else
					tinsert(text, format("cNcA%s점 cW(겨울손아귀 호수)", s, p))
				end
			end
		elseif codes[i][1] == "J" then
			c, s, p = strsplit("@", codes[i][2])
			t = "cNcI정의의 휘장("..s
			if p == "1" then
				tinsert(text, t..", cI쿠엘다나스 섬)" )
			else
				tinsert(text, t..", cI샤트라스)")
			end
		elseif codes[i][1] == "Y" then
			c, s = strsplit("@", codes[i][2])
			tinsert(text, "cNcI용맹의 문장("..s..")")
		elseif codes[i][1] == "M" then
			c, s = strsplit("@", codes[i][2])
			tinsert(text, "cNcI무용의 문장("..s..")")
		elseif codes[i][1] == "S" then
			n = self:GetCategoryName(codes[i][2])
			tinsert(text, "cQ|cffeaeaea"..n[2])
		elseif codes[i][1] == "T" then
			c, s = strsplit("@", codes[i][2])
			n = self:GetCategoryName(c) or {}
			if n[2] and reputation[s] then
				tinsert(text, "cNcT"..n[2].."cW"..reputation[s])
			end
		elseif codes[i][1] == "Q" then
			c, sz, ql, qn = strsplit("@", codes[i][2])
			n = self:GetCategoryName(c)
			tinsert(text, "cN|cffbfefff"..n[3].." |cff9ac0cd"..sz)
			tinsert(text, "cQ["..ql.."] "..qn)
		elseif codes[i][1] == "W" then
			tinsert(text, "cN월드 드랍")
		elseif codes[i][1] == "C" then
			tinsert(text, "cN"..codes[i][2])
		elseif codes[i][1] == "X" then
			text = { "cN"..codes[i][2] }
			break
		elseif codes[i][1] == "s" then
			c, s = strsplit("@", codes[i][2])
			oid = tonumber(c)
			otext = self:GetItemText(oid) or { "cN드랍 미확인" }
			oname = N_cache[oid]
			if otext and oname then
				oname = oname..(s and (", "..s) or "")
				if strfind(otext[1], "▷") then
					tinsert(text, "cN드랍 미확인".." (cI"..oname.."cW)")
				else
					for i = 1, #otext do
						if strfind(otext[i], "▶") then
							tinsert(text, otext[i].." (cI"..oname.."cW)")
						end
					end
				end
			end
		elseif codes[i][1] == "n" then
			N_cache[id] = codes[i][2]
		end
	end
	for i = 1, #(text) do
		for p, v in pairs(swich) do
			text[i] = gsub(text[i], p, v)
		end
		text[i] = gsub(text[i], "%(", "|cffffffff(")
	end
	if #(text) > 0 then
		cache[id] = text
	end
	return text
end

function BlueItemInfo2:OnTooltipUpdate()
	GameTooltip:AddLine("BlueItemInfo2")
	GameTooltip:AddLine("좌클릭: UI창 토글", 0.2, 1, 0.2)
	GameTooltip:AddLine("우클릭: 설정", 0.2, 1, 0.2)
end

function BlueItemInfo2:GetItemInfo(id)
	if not id then return end
	if id > 0 then
		itemName, itemLink, itemRarity = GetItemInfo(id)
		if itemName then
			return itemName, format("%s%s|r", select(4, GetItemQualityColor(itemRarity)) or "", itemName), itemLink, GetItemIcon(id)
		else
			return nil, nil, nil, GetItemIcon(id) or "Interface\\Icons\\INV_Misc_QuestionMark"
		end
	elseif id < 0 then
		id = -id
		itemName, _, itemRarity = GetSpellInfo(id)
		if itemName then
			if itemRarity == nil or itemRarity == "" or itemRarity == "Interface\\Icons\\Temp" then
				itemRarity = "Interface\\Icons\\Spell_Holy_GreaterHeal"
			end
			return itemName, format("|cffffd000%s|r", itemName), GetSpellLink(id), itemRarity
		else
			return nil, nil, nil, "Interface\\Icons\\INV_Misc_QuestionMark"
		end
	end
end

function BlueItemInfo2:GetItemData(id)
	if id then
		return self.data.itemDB[id] or self.data.itemDB1[id] or self.data.itemDB0[id]
	else
		return nil
	end
end

function BlueItemInfo2:GetItemCode(id)
	item = self:GetItemData(id)
	if item then
		if type(item) == "string" then
			return item
		else
			item = self:GetItemData(item)
			if type(item) == "string" then
				return item
			else
				item = self:GetItemData(item)
				if type(item) == "string" then
					return item
				else
					return nil
				end
			end
		end
	else
		return nil
	end
end

function BlueItemInfo2:GetItemRealText(id)
	if self:GetItemData(id) then
		item = self:GetItemCode(id)
		if item and type(item) == "string" then
			f = strsub(UnitFactionGroup("player"), 1, 1)
			if strfind(item, "^v|") then
				if self.data.cver == self.data.nver or self.data.cver == ("0"..strsub(self.data.nver, 2)) then
					item = strsub(item, 2)
				else
					return nil
				end
			end
			if strfind(item, "^a|") then
				if f == "A" then
					return gsub(item, "^a|", "")
				else
					return nil
				end
			elseif strfind(item, "^h|")  then
				if f == "H" then
					return gsub(item, "^h|", "")
				else
					return nil
				end
			end
			return item
		end
	end
	return nil
end

function BlueItemInfo2:GetItemValue(id)
	id = tonumber(id)
	item = self:GetItemRealText(id)
	if not item then return {} end
	codes, db, itemType, itemCode = {}, { strsplit("|", item) }
	for i = 1, #(db) do
		itemType, itemCode = strsplit("_", db[i])
		if itemType and itemCode == nil then
			codes[i] = { nil, itemType }
		else
			codes[i] = { itemType, itemCode }
		end
	end
	return codes
end

function BlueItemInfo2:GetCategory(code)
	code = code or BlueItemInfo2DB.category
	return { strsub(code, 1, 1), strsub(code, 2, 2), strsub(code, 3, 3) }
end

function BlueItemInfo2:GetCategoryName(code)
	if not(code and self.data.categoryCode[code]) then return end
	c = self:GetCategory(code)
	name = { strsplit("_", self.data.categoryCode[c[1]..c[2].."0"]) }
	if c[3] ~= "0" then
		name[3] = self.data.categoryCode[code]
	elseif #(name) == 1 then
		name[2] = ""
		name[3] = ""
	elseif #(name) == 2 then
		name[3] = ""
	end
	return name
end

local itemLink

function BlueItemInfo2:GetItemCache(itemID)
	if itemID and itemID ~= "" then
		itemLink = "item:"..itemID
		if GetItemInfo(itemLink) then
			self:PrintItem(itemLink)
		elseif GetItemIcon(itemLink) then
			GameTooltip:SetOwner(this, "ANCHOR_NONE")
			GameTooltip:SetHyperlink(itemLink)
			GameTooltip:Hide()
			self:ScheduleEvent("BlueItemInfoPrintItem", "PrintItem", 1, self, itemLink)
		else
			ChatFrame1:AddMessage("|cffFFFF7F[BlueItemInfo2]|r "..itemID..": 서버에 존재하지 않습니다.")
		end
	end
end

local itemName, itemLink, itemID, head

function BlueItemInfo2:PrintItem(link)
	if link then
		itemName, itemLink = GetItemInfo(link)
		itemID = strmatch(link..":", "item:(%d+):")
		head = "|cffFFFF7F[BlueItemInfo2]|r "..itemID..": "
		if itemName then
			itemID = select(3, strfind(itemLink, "item:(%d+):"))
			ChatFrame1:AddMessage(head..itemLink)
		else
			ChatFrame1:AddMessage(head.."서버에 존재하지 않습니다.")
		end
	end
end

BlueItemInfo2:OnInit()
BlueItemInfo2:RegisterEvent("PLAYER_ENTERING_WORLD")