local addOnName = ...
local BII3 = CreateFrame("Frame", addOnName, UIParent)
BII3:SetScript("OnEvent", function(self, event, ...) self[event](self, ...) end)
BII3:RegisterEvent("PLAYER_LOGIN")
BII3:Hide()
BII3:SetToplevel(true)
BII3.isHorde = UnitFactionGroup("player") == "Horde"
BII3.codeList = "ABCDEFGH0123456789abcdefghijklmnopqrstuvwxyzIJKLMNOPQRSTUVWXYZ"
BII3.codeListLen = BII3.codeList:len()
BII3.codeListZero = BII3.codeList:find("0")

local _G = _G
local select = _G.select
local ipairs = _G.ipairs
local tonumber = _G.tonumber
local loadstring = _G.loadstring
local UnitLevel = _G.UnitLevel
local GetSpellInfo = _G.GetSpellInfo
local GetItemIcon = _G.GetItemIcon
local GetItemQualityColor = _G.GetItemQualityColor
local GetAddOnMetadata = _G.GetAddOnMetadata
local category, category1, category2, packIndex

BII3.itemDB, BII3.categoryCode = {}, {}

SLASH_BLUEITEMINFO1 = "/bii"
SLASH_BLUEITEMINFO2 = "/blueiteminfo"
SLASH_BLUEITEMINFO3 = "/아이템인포"
SlashCmdList["BLUEITEMINFO"] = function() BlueItemInfo3:OnClick() end
BINDING_HEADER_BLUEITEMINFO3 = "Blue Item Info 3"
BINDING_NAME_BLUEITEMINFO3_TOGGLE = "UI창 열기/닫기"
BINDING_NAME_BLUEITEMINFO3_OPTION = "설정창 열기/닫기"

function BII3:PLAYER_LOGIN()
	self:UnregisterEvent("PLAYER_LOGIN")
	self.PLAYER_LOGIN = nil
	local LBDB = LibStub("LibBlueDB-1.0")
	local function newTable() return {} end
	BlueItemInfo3DB = BlueItemInfo3DB or {}
	BlueItemInfo3CharDB = BlueItemInfo3CharDB or {}
	BlueItemInfo3ItemNameDB = BlueItemInfo3ItemNameDB or {}
	self.db = LBDB:RegisterDB(BlueItemInfo3DB, {
		code = nil,
		scale = 1,
		anchor = "CENTER",
		px = 0,
		py = 0,
		height = 312,
		drop = true,
		count = true,
		memo = {},
		dataPacks = { LK = true, BC = true, Original = true },
		minimapButton = { show = true, dragable = true, angle = 183 },
	}, newTable)
	self.chardb = LBDB:RegisterDB(BlueItemInfo3CharDB, {
		favorite = { [0] = {}, [1] = {}, [2] = {}, [3] = {}, [4] = {}, [5] = {}, [6] = {}, [7] = {}, [8] = {}, [9] = {} },
	}, newTable)
	self.itemNameDB = BlueItemInfo3ItemNameDB
	for id in pairs(self.itemNameDB) do
		if GetAddOnMetadata(addOnName.."_UI", "X-DB-ItemName-"..id) then
			self.itemNameDB[id] = nil
		end
	end
	setmetatable(self.itemDB, {
		__index = function(_, key)
			if key then
				for pack, use in pairs(self.db.dataPacks) do
					if use then
						use = GetAddOnMetadata(addOnName.."_"..pack, "X-DB-Info-"..key)
						if use then
							return loadstring("return "..use)()
						end
					end
				end
			end
			return nil
		end,
		__newindex = function() end,
	})
	LibStub("LibItemTooltip-2.0"):Register(self, "ProcessTooltip")
	LibStub("LibMapButton-1.1"):CreateButton(self, "BlueItemInfo3MapButton", "Interface\\AddOns\\BlueItemInfo3\\Icon", 183, BlueItemInfo3DB.minimapButton)
	LibStub("LibDataBroker-1.1"):NewDataObject("BlueItemInfo3", {
		type = "launcher",
		text = "BII3",
		OnClick = self.OnClick,
		icon = "Interface\\AddOns\\BlueItemInfo3\\Icon",
		OnTooltipShow = function(tooltip)
			if tooltip and tooltip.AddLine then
				BII3:OnTooltip(tooltip)
			end
		end,
	})
	self.optionFrame = CreateFrame("Frame", addOnName.."OptionFrame", InterfaceOptionsFramePanelContainer)
	self.optionFrame:Hide()
	self.optionFrame.name = "블루 아이템 인포 3"
	self.optionFrame:SetScript("OnShow", function(self)
		self:SetScript("OnShow", nil)
		LoadAddOn(addOnName.."_Option")
	end)
	InterfaceOptions_AddCategory(self.optionFrame)
end

function BII3:OnClick(button)
	if button == "RightButton" then
		if InterfaceOptionsFramePanelContainer.displayedPanel == BII3.optionFrame then
			InterfaceOptionsFrameOkay_OnClick()
		else
			InterfaceOptionsFrame_OpenToCategory(BII3.optionFrame)
		end
	elseif BII3:IsShown() then
		BII3:Hide()
	else
		BII3:Show()
	end
end

function BII3:OnTooltip(tooltip)
	tooltip = tooltip or GameTooltip
	tooltip:AddLine("Blue Item Info 3 v"..GetAddOnMetadata(addOnName, "Version").."."..GetAddOnMetadata(addOnName.."_UI", "X-DB-NumItems"))
	tooltip:AddLine(GetAddOnMetadata(addOnName, "X-Website"), 1, 1, 1)
	tooltip:AddLine("좌클릭: 창 열기", 1, 1, 0)
	tooltip:AddLine("우클릭: 옵션창 열기", 1, 1, 0)
end

local rarity, name
local tooltip = CreateFrame("GameTooltip")
tooltip[1] = tooltip:CreateFontString(nil, "OVERLAY", "GameFontNormal")
tooltip:AddFontStrings(tooltip[1], tooltip:CreateFontString(nil, "OVERLAY", "GameFontNormal"))

local function isEnchantSpell(id, spell)
	tooltip:Hide()
	tooltip:ClearLines()
	tooltip:SetOwner(UIParent, "ANCHOR_NONE")
	tooltip:SetHyperlink("enchant:"..id)
	tooltip:Show()
	if tooltip[1]:IsShown() and select(3, tooltip[1]:GetTextColor()) == 0 and tooltip[1]:GetText() and tooltip[1]:GetText() ~= "" then
		if spell then
			return tooltip[1]:GetText():find(spell:gsub("%-", "%%-") or "") and tooltip[1]:GetText() or spell
		else
			return true
		end
	else
		return nil
	end
end

local function getItemName(id)
	return BII3.itemNameDB[id] or GetAddOnMetadata(addOnName.."_UI", "X-DB-ItemName-"..id)
end

function BII3:IsItem(id)
	if id < 0 then
		return GetSpellInfo(-id) and true or nil
	else
		return getItemName(id) and true or nil
	end
end

function BII3:GetItemName(id)
	if id < 0 then
		return GetSpellInfo(-id) or "미확인 주문"
	else
		id = getItemName(id)
		if id then
			return id:match("|(.+)")
		else
			return "미확인 아이템"
		end
	end
end

function BII3:GetItemColorName(id)
	if id < 0 then
		id = -id
		name = GetSpellInfo(id)
		if name then
			rarity = isEnchantSpell(id, name)
			if rarity then
				return "|cffffd000"..rarity.."|r"
			else
				return "|cff71d5ff"..name.."|r"
			end
		else
			return "|cffffffff미확인 주문|r"
		end
	else
		id = getItemName(id)
		if id then
			rarity, name = ("|"):split(id)
			return select(4, GetItemQualityColor(rarity))..name.."|r"
		else
			return "|cffffffff미확인 아이템|r"
		end
	end
end

function BII3:GetLinkID(link)
	if link:find("item:(%d+)") then
		link = tonumber(link:match("item:(%d+)"))
	elseif link:find("spell:(%d+)") then
		link = -tonumber(link:match("spell:(%d+)"))
	elseif link:find("enchant:(%d+)") then
		link = -tonumber(link:match("enchant:(%d+)"))
	else
		return nil
	end
	return link
end

function BII3:GetItemLink(id)
	if id < 0 then
		id = -id
		name = GetSpellInfo(id)
		if name then
			rarity = isEnchantSpell(id, name)
			if rarity then
				return ("|cffffd000|Henchant:%d|h[%s]|h|r"):format(id, rarity)
			else
				return ("|cff71d5ff|Hspell:%d|h[%s]|h|r"):format(id, name)
			end
		end
	else
		name = getItemName(id)
		if name then
			rarity, name = ("|"):split(name)
			return ("%s|Hitem:%d:0:0:0:0:0:0:0:%d:0|h[%s]|h|r"):format(select(4, GetItemQualityColor(rarity)), id, UnitLevel("player"), name)
		end
	end
	return nil
end

function BII3:GetItemSimpleLink(id)
	if id < 0 then
		id = -id
		return ("%s:%d"):format(isEnchantSpell(id) and "enchant" or "spell", id)
	else
		return ("item:%d:0:0:0:0:0:0:0:%d:0"):format(id, UnitLevel("player"))
	end
end

function BII3:GetItemIcon(id)
	if id > 0 then
		return GetItemIcon(id) or "Interface\\Icons\\INV_Misc_QuestionMark"
	elseif id < 0 then
		return select(3, GetSpellInfo(-id)) or "Interface\\Icons\\INV_Misc_QuestionMark"
	else
		return "Interface\\Icons\\INV_Misc_QuestionMark"
	end
end

function BII3:ReplaceFactionText(text)
	if text:find("$f{") then
		text = text:gsub("$f{([^{}]+)/([^{}]+)}", self.isHorde and "%1" or "%2")
	end
	return text
end

function BII3:GetCategory(code)
	return code and self.categoryCode[code] or GetAddOnMetadata(addOnName, "X-DB-Category-"..code:gsub("[A-Z]", "!%1"))
end

function BII3:GetCategoryName(code)
	category = self:GetCategory(code)
	if category then
		if code:find("0$") then
			category1, category2, category = ("_"):split(category)
		else
			category1 = self:GetCategory(code:sub(1, 2).."0")
			if category1 then
				category1, category2 = ("_"):split(category1)
			else
				return nil
			end
		end
		return category1, self:ReplaceFactionText(category2), category and self:ReplaceFactionText(category) or nil
	else
		return nil
	end
end

BII3:SetScript("OnShow", function(self)
	self:SetScript("OnShow", nil)
	LoadAddOn(addOnName.."_UI")
	if not(type(self.db.code) == "string" and self.db.code:len() == 3 and self.itemList[self.db.code]) then
		self.db.code = nil
		for i = 3, self.codeListLen do
			if self.itemList[self.codeList:sub(i, i).."**"] then
				for j = self.codeListZero, self.codeListLen do
					if self.itemList[self.codeList:sub(i, i)..self.codeList:sub(j, j).."*"] then
						for k = self.codeListZero, self.codeListLen do
							if self.itemList[self.codeList:sub(i, i)..self.codeList:sub(j, j)..self.codeList:sub(k, k)] then
								self.db.code = self.codeList:sub(i, i)..self.codeList:sub(j, j)..self.codeList:sub(k, k)
								break
							end
						end
					end
					if self.db.code then
						break
					end
				end
			end
			if self.db.code then
				break
			end
		end
		if not self.db.code then
			return self:Hide()
		end
	end
	collectgarbage()
	self:Update()
end)

function BII3:ModifiedItemClick(link)
	if type(link) == "string" and (link:find("item:") or link:find("spell:") or link:find("enchant:")) then
		if IsControlKeyDown() and IsShiftKeyDown() then
			self:AddMemo(self:GetLinkID(link))
			return true
		elseif IsAltKeyDown() then
			self:AddFavorite(self:GetLinkID(link))
			return true
		end
	end
	return nil
end

local oldChatFrame_OnHyperlinkShow = ChatFrame_OnHyperlinkShow

function ChatFrame_OnHyperlinkShow(self, link, text, button)
	 local bret = false
   if IsModifiedClick() then
      if self ~= COMBATLOG and button == "LeftButton" then
          bret = BII3:ModifiedItemClick(link)
      end
   end
   if not bret then
       oldChatFrame_OnHyperlinkShow(self, link, text, button)
   end
end
