local _G = getfenv(0)
local tonumber = _G.tonumber
local pairs = _G.pairs
local strfind = _G.string.find
local strsub = _G.string.sub
local strsplit = _G.strsplit
local GetItemInfo = _G.GetItemInfo
local GetItemIcon = _G.GetItemIcon
local GetMouseFocus = _G.GetMouseFocus
local CreateFrame = _G.CreateFrame
local PlaySound = _G.PlaySound
local CursorUpdate = _G.CursorUpdate
local SetItemButtonTexture = _G.SetItemButtonTexture
local SetItemButtonTextureVertexColor = _G.SetItemButtonTextureVertexColor
local IsAddOnLoaded = _G.IsAddOnLoaded

local DropMenu = LibStub("LibDropMenu-1.0")

local v36 = "ABC0123456789abcdefghijklmnopqrstuvwxyz"
local backdrop = {
	bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
	edgeFile = "Interface\\Addons\\BlueItemInfo2\\Texture\\Border",
	tile = true, tileSize = 16, edgeSize = 16,
	insets = { left = 2, right = 2, top = 2, bottom = 2 }
}

DropMenu:RegisterMenu("BlueItemInfo2", {
	type = "group",
	icon = BlueItemInfo2.icon,
	name = "Blue Item Info 2",
	args = {
		gui = {
			type = "execute",
			name = "열기/닫기",
			desc = "GUI창을 열고 닫습니다.",
			order = 1,
			func = function() BlueItemInfo2:OnClick() end,
		},
		item = {
			type = "text",
			name = "ID",
			desc = "아이템 ID로 아이템을 확인합니다.",
			order = 2,
			usage = "",
			get = function() return "" end,
			set = function(v) BlueItemInfo2:GetItemCache(v) end,
		},
		show = {
			type = "toggle",
			name = "아이템 획득 경로 표시",
			desc = "툴팁에 아이템의 획득 경로를 표시합니다.",
			order = 3,
			get = function() return BlueItemInfo2DB.info end,
			set = function() BlueItemInfo2DB.info = not BlueItemInfo2DB.info end,
		},
		itemid = {
			type = "toggle",
			name = "아이템 ID 표시",
			desc = "툴팁에 아이템 ID를 표시합니다.",
			order = 4,
			get = function() return BlueItemInfo2DB.id end,
			set = function() BlueItemInfo2DB.id = not BlueItemInfo2DB.id end,
		},
		itemlv = {
			type = "toggle",
			name = "아이템 레벨 표시",
			desc = "툴팁에 아이템 레벨을 표시합니다.",
			order = 5,
			get = function() return BlueItemInfo2DB.level end,
			set = function() BlueItemInfo2DB.level = not BlueItemInfo2DB.level end,
		},
		sort = {
			type = "toggle",
			name = "목록내 아이템 정렬",
			desc = "GUI의 아이템 목록에서 아이템을 정렬합니다.",
			order = 6,
			get = function() return BlueItemInfo2DB.sort end,
			set = function() BlueItemInfo2DB.sort = not BlueItemInfo2DB.sort end,
		},
		esc = {
			type = "toggle",
			name = "ESC 창닫기",
			desc = "ESC키로 GUI창을 닫습니다.",
			order = 7,
			get = function() return BlueItemInfo2DB.esc end,
			set = function()
				BlueItemInfo2DB.esc = not BlueItemInfo2DB.esc
				if BlueItemInfo2DB.esc then
					tinsert(UISpecialFrames, "BlueItemInfoGUI")
				else
					for p, v in pairs(UISpecialFrames) do
						if v == "BlueItemInfoGUI" then
							tremove(UISpecialFrames, p)
							break
						end
					end
				end
			end,
		},
		scale = {
			type = "range",
			name = "크기 조절",
			desc = "GUI의 크기를 조절합니다.",
			order = 8,
			get = function() return BlueItemInfo2DB.scale end,
			set = function(v)
				BlueItemInfo2DB.scale = v
				if BlueItemInfo2.GUI then
					BlueItemInfo2.GUI:SetScale(v)
				end
			end,
			min = 0.5,
			max = 1.5,
			step = 0.1,
		},
		backdrop = {
			type = "color",
			name = "배경 색상",
			desc = "UI창의 배경 색상을 설정합니다.",
			order = 9,
			get = function() return unpack(BlueItemInfo2DB.backdrop) end,
			set = function(r, g, b, a)
				BlueItemInfo2DB.backdrop = { r, g, b, a }
				if BlueItemInfo2.GUI then
					BlueItemInfo2.GUI:SetBackdropColor(r, g, b, a)
				end
			end,
			hasAlpha = true,
		},
		mmButton = {
			type = "group",
			name = "미니맵 버튼",
			desc = "미니맵 버튼을 조정합니다.",
			order = 10,
			args = {
				lock = {
					type = "toggle",
					name = "미니맵 버튼 잠금",
					desc = "미니맵 버튼을 잠가 이동시키지 못하게 합니다.",
					order = 1,
					get = function() return not BlueItemInfo2DB.minimapButton.dragable end,
					set = function() BlueItemInfo2DB.minimapButton.dragable = not BlueItemInfo2DB.minimapButton.dragable end,
				},
				toggle = {
					type = "toggle",
					name = "미니맵 버튼 보이기",
					desc = "미니맵 버튼을 보이거나 숨깁니다.",
					order = 2,
					get = function() return BlueItemInfo2DB.minimapButton.show end,
					set = function()
						BlueItemInfo2DB.minimapButton.show = not BlueItemInfo2DB.minimapButton.show
						if BlueItemInfo2MiniMapButton then
							BlueItemInfo2MiniMapButton:Toggle()
						end
					end,
				},
			},
			hidden = function() return not BlueItemInfo2MiniMapButton end,
		},
	},
})

function BlueItemInfo2:CreateCategory()
	self.menu = { type = "group", args = {} }
	local ncache = {}
	local c, name
	for code in pairs(self.data.categoryCode) do
		c = self:GetCategory(code)
		if self.data.items[code] or strfind("ABC", c[1]) then
			if not(self.menu.args[c[1]]) then
				name = ncache[c[1].."00"] or self:GetCategoryName(c[1].."00")
				ncache[c[1].."00"] = name
				self.menu.args[c[1]] = {
					name = c[1] == "A" and "즐겨찾기" or name[1],
					desc = c[1] == "A" and UnitName("player").."의 즐겨찾기 목록" or name[1].."의 목록",
					type = "group",
					order = strfind("ABC", c[1]) or tonumber(c[1], 36) + 4,
					args = {},
				}
			end
			if not(self.menu.args[c[1]].args[c[2]]) then
				name = ncache[c[1]..c[2].."0"] or self:GetCategoryName(c[1]..c[2].."0")
				ncache[c[1]..c[2].."0"] = name
				self.menu.args[c[1]].args[c[2]] = {
					name = name[2],
					desc = name[2].."의 목록",
					type = "group",
					order = tonumber(c[2], 36) + 1,
					args = {},
				}
			end
			local name = ncache[code] or self:GetCategoryName(code)
			if name[2] == "" then
				self.menu.args[c[1]] = {
					name = name[1],
					desc = name[1].."의 아이템 목록",
					type = "execute",
					order = strfind("ABC", c[1]) or tonumber(c[1], 36) + 4,
					func = function() self:MenuOnClick(code) end,
				}
			elseif name[3] == "" then
				self.menu.args[c[1]].args[c[2]] = {
					name = name[2],
					desc = name[2].."의 아이템 목록",
					type = "execute",
					order = tonumber(c[2], 36) + 1,
					func = function() self:MenuOnClick(code) end,
				}
			else
				self.menu.args[c[1]].args[c[2]].args[c[3]] = {
					name = name[3],
					desc = name[3].."의 아이템 목록",
					type = "execute",
					order = tonumber(c[3], 36) + 1,
					func = function() self:MenuOnClick(code) end,
				}
			end
		else
			if BlueItemInfo2DB.category == code then
				BlueItemInfo2DB.category = self.defalutCode
			end
		end
	end
	ncache = nil
end

function BlueItemInfo2:CreateGUI()
	local scrollbackdrop = {
		bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
		edgeFile = "Interface\\Addons\\BlueItemInfo2\\Texture\\ScrollBar",
		tile = true, tileSize = 16,  edgeSize = 16,
		insets = {left = 4, right = 4, top = 4, bottom = 4},
	}
	local frame = CreateFrame("Frame", "BlueItemInfoGUI", UIParent)
	self.GUI = frame
	frame:SetWidth(628)
	frame:SetHeight(BlueItemInfo2DB.height)
	frame:SetPoint(BlueItemInfo2DB.pos[1], UIParent, BlueItemInfo2DB.pos[1], BlueItemInfo2DB.pos[2], BlueItemInfo2DB.pos[3])
	frame:EnableMouse()
	frame:SetMovable(true)
	frame:SetResizable(true)
	frame:SetMinResize(628, 108)
	frame:SetMaxResize(628, 628)
	frame:SetFrameStrata("MEDIUM")
	frame:SetToplevel(true)
	frame:SetBackdrop(backdrop)
	if Skinner then
		Skinner:applySkin(BlueItemInfoGUI, nil, nil, nil, nil, backdrop)
	end
	if VisualThemes then
		VisualThemes:RegisterAddOn("BlueItemInfo2", "BlueItemInfo2", 2, "BlueItemInfoGUI", "BlueItemInfo2GUIScroll")
	end
	if BlueItemInfo2DB.esc then
		tinsert(UISpecialFrames, "BlueItemInfoGUI")
	end
	frame:SetBackdropColor(unpack(BlueItemInfo2DB.backdrop))
	frame:SetScript("OnShow", function() PlaySound("igCharacterInfoOpen") end)
	frame:SetScript("OnHide", function()
		BlueItemInfo2:CloseDropMenu()
		PlaySound("igCharacterInfoClose")
		collectgarbage()
	end)
	frame:SetScript("OnDragStart", function(self) self:StartMoving() end)
	frame:SetScript("OnDragStop", function(self)
		self:StopMovingOrSizing()
		local p, _, _, x, y = self:GetPoint()
		BlueItemInfo2DB.pos = { p, x, y }
	end)
	frame:SetClampedToScreen(true)
	frame:RegisterForDrag("LeftButton")
	local icon = CreateFrame("Button", nil, frame)
	icon:SetWidth(18)
	icon:SetHeight(18)
	icon:RegisterForClicks("LeftButtonUp", "RightButtonUp")
	icon:SetNormalTexture(self.icon)
	icon:SetPoint("TOPLEFT", frame, "TOPLEFT", 6, -6)
	icon:SetScript("OnClick", function(self)
		if DropMenu:IsOpen("BlueItemInfo2") then
			PlaySound("igMainMenuOptionCheckBoxOff")
			BlueItemInfo2:CloseDropMenu()
		else
			PlaySound("igMainMenuOptionCheckBoxOn")
			DropMenu:OpenMenu("BlueItemInfo2", "TOPLEFT", self, "CENTER", 0, 0)
		end
	end)
	local name = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	name:SetPoint("TOP", frame, "TOP", 0, -7)
	name:SetText("Blue Item Info 2 |cffffffffv"..self.version.."."..self.data.num.."|r ("..self.website..")")
	local closebutton = CreateFrame("Button", nil, frame, "UIPanelCloseButton")
	closebutton:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 2, 2)
	closebutton:SetScript("OnClick", function() frame:Hide() end)
	for i = 1, 3 do
		frame["drop"..i] = self:CreateDropdownFrame(i)
	end
	frame.drop1:SetPoint("TOPLEFT", frame, "TOPLEFT", 5, -24)
	frame.drop2:SetPoint("LEFT", frame.drop1, "RIGHT", 0, 0)
	frame.drop3:SetPoint("LEFT", frame.drop2, "RIGHT", 0, 0)
	local nolist = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	frame.nolist = nolist
	nolist:SetPoint("CENTER", frame, "CENTER", 0, -20)
	nolist:SetText("|cffffffff아이템 정보가 없습니다.|r")
	nolist:Hide()
	local scrollframe = CreateFrame("ScrollFrame", "BlueItemInfo2GUIScroll", frame, "UIPanelScrollFrameTemplate")
	local scrollchild = CreateFrame("Frame", "BlueItemInfo2GUIScrollChild", scrollframe)
	scrollframe:SetScrollChild(scrollchild)
	scrollframe:SetPoint("TOPLEFT", frame, "TOPLEFT", 7, -50)
	scrollframe:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -27, 5)
	scrollframe:SetScript("OnMouseWheel", function(self)
		BlueItemInfo2:CloseDropMenu()
		ScrollFrameTemplate_OnMouseWheel(self, arg1)
	end)
	scrollchild:SetWidth(594)
	scrollchild:SetHeight(45)
	for k, v in pairs({ scrollframe:GetRegions() }) do
		if regions then
			for _, r in pairs(regions) do
				if k == r then
					v:SetAlpha(0)
					break
				end
			end
		else
			v:SetAlpha(0)
		end
	end
	local scrollbar = BlueItemInfo2GUIScrollScrollBar
	scrollbar:SetBackdrop(scrollbackdrop)
	scrollbar:SetBackdropBorderColor(0.2, 0.2, 0.2, 1)
	scrollbar:SetBackdropColor(0.1, 0.1, 0.1, 1)
	frame.scrollframe = scrollframe
	frame.scrollchild = scrollchild
	frame.scrollbar = scrollbar
	local sizer = CreateFrame("Frame", nil, frame)
	sizer:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", 0, 0)
	sizer:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 0, 0)
	sizer:SetHeight(10)
	sizer:EnableMouse()
	sizer:SetScript("OnMouseDown", function()
		BlueItemInfo2:CloseDropMenu()
		frame:StartSizing("BOTTOM")
	end)
	sizer:SetScript("OnMouseUp", function()
		frame:StopMovingOrSizing()
		BlueItemInfo2DB.height = frame:GetHeight()
		local p, _, _, x, y = frame:GetPoint()
		BlueItemInfo2DB.pos = { p, x, y }
	end)
	frame:SetScale(BlueItemInfo2DB.scale)
	self:SetCategory()
	PlaySound("igCharacterInfoOpen")
end

function BlueItemInfo2:CloseDropMenu()
	DropMenu:CloseMenu(1)
	self.OpenedItemFrameMenu = nil
	DropMenu:UnregisterMenu("BlueItemInfo2ItemFrameMenu")
	DropMenu:UnregisterMenu("BlueItemInfo2ItemMenu1")
	DropMenu:UnregisterMenu("BlueItemInfo2ItemMenu2")
	DropMenu:UnregisterMenu("BlueItemInfo2ItemMenu3")
end

local function iframeOnEnter(frame)
	GameTooltip:SetOwner(frame, "ANCHOR_NONE")
	GameTooltip:SetPoint("TOPLEFT", frame, "BOTTOMLEFT", -2, 0)
	local id = frame.itemID
	if id > 0 then
		if GetItemInfo(id) then
			GameTooltip:SetHyperlink("item:"..id)
		else
			GameTooltip:SetText("|cffffffff해당 아이템이 아이템 캐쉬에 존재하지 않습니다.|r")
			GameTooltip:AddLine("클릭하면 해당 아이템의 정보를 서버로부터 가져옵니다.")
			BlueItemInfo2:ProcessTooltip(GameTooltip, nil, "item:"..id, id)
		end
	elseif id < 0 then
		GameTooltip:SetHyperlink("enchant:"..abs(id))
	else
		GameTooltip:Hide()
		return
	end
	GameTooltip:Show()
end

local function iframeOnLeave(frame)
	GameTooltip:Hide()
	ShoppingTooltip1:Hide()
	ShoppingTooltip2:Hide()
	ResetCursor()
end

local function iframeOnUpdate(frame, elt)
	if not(frame.compItem) and frame.itemID > 0 and IsModifiedClick("COMPAREITEMS") then
		frame.compItem = true
		GameTooltip_ShowCompareItem()
	elseif frame.compItem and not(IsModifiedClick("COMPAREITEMS")) then
		frame.compItem = nil
		ShoppingTooltip1:Hide()
		ShoppingTooltip2:Hide()
	end
	frame.updateTimer = (frame.updateTimer or 0) + elt
	if GetMouseFocus() == frame then
		if frame.itemID and frame.itemID > 0 then
			frame.hasItem = true
			if frame.updateTimer >= 1 and GameTooltip:IsVisible() and GetItemInfo(frame.itemID) then
				frame.updateTimer = 0
				iframeOnEnter(frame)
			end
		else
			frame.hasItem = nil
		end
		CursorUpdate(frame)
	end
end

local function iframeOnClick(frame)
	local id = frame.itemID
	local itemName, itemColorName, itemLink, itemTexture = BlueItemInfo2:GetItemInfo(id)
	if arg1 == "LeftButton" then
		if itemName then
			if id > 0 and IsShiftKeyDown() and IsControlKeyDown() then
				BlueItemInfo2:AddMemo(id)
			elseif IsAltKeyDown() then
				BlueItemInfo2:AddFavoriteItem(id)
			elseif IsModifiedClick("CHATLINK") then
				if id > 0 and AuctionFrame and AuctionFrame:IsVisible() and BrowseName:IsVisible() then
					BrowseName:SetText(itemName)
				else
					ChatFrameEditBox:Show()
					ChatFrameEditBox:Insert(itemLink)
				end
			elseif IsModifiedClick("DRESSUP") then
				DressUpItemLink(itemLink)
			else
				ChatFrame_OnHyperlinkShow(itemLink, itemLink)
			end
		else
			GameTooltip:SetOwner(frame, "ANCHOR_NONE")
			GameTooltip:SetHyperlink("item:"..id..":0:0:0:0:0:0:0")
			GameTooltip:Hide()
			BlueItemInfo2:CancelScheduledEvent("BlueItemInfoReflash")
			BlueItemInfo2:ScheduleEvent("BlueItemInfoReflash", "SetItemList", 1, self, BlueItemInfo2DB.category)
		end
		BlueItemInfo2:CloseDropMenu()
	elseif DropMenu:IsOpen("BlueItemInfo2ItemFrameMenu") and BlueItemInfo2.OpenedItemFrameMenu == itemLink then
		BlueItemInfo2:CloseDropMenu()
	elseif id then
		if itemName then
			DropMenu:RegisterMenu("BlueItemInfo2ItemFrameMenu", { type = "group", args = {
				name = { type = "header", name = itemColorName, order = 1, icon = itemTexture },
				link = { type = "execute", name = "채팅창에 링크", desc = "아이템을 채팅창에 링크합니다.\nShift+클릭", order = 2, func = function()
					ChatFrameEditBox:Show()
					ChatFrameEditBox:Insert(itemLink)
					BlueItemInfo2:CloseDropMenu()
				end },
				view = { type = "execute", name = "미리보기", desc = "아이템을 미리 입어봅니다.\nCtrl+클릭", order = 3, func = function()
					DressUpItemLink(itemLink)
					BlueItemInfo2:CloseDropMenu()
				end },
				fav = { type = "execute", name = "즐겨찾기 추가/삭제", desc = "아이템을 즐겨찾기에 추가 및 삭제합니다.\nAlt+클릭", order = 4, func = function()
					BlueItemInfo2:AddFavoriteItem(id)
					BlueItemInfo2:CloseDropMenu()
				end },
				memo = { type = "execute", name = "메모", desc = "아이템에 메모를 작성합니다.\nShift+Ctrl+클릭", order = 5, func = function()
					BlueItemInfo2:AddMemo(id)
					BlueItemInfo2:CloseDropMenu()
				end },
			}})
			DropMenu:OpenMenu("BlueItemInfo2ItemFrameMenu", "TOPLEFT", frame, "CENTER")
			BlueItemInfo2.OpenedItemFrameMenu = itemLink
		else
			DropMenu:RegisterMenu("BlueItemInfo2ItemFrameMenu", { type = "group", args = { ident = {
				type = "execute",
				name = "미확인 아이템 확인",
				desc = "미확인 아이템의 정보를 서버로부터 가져옵니다.\n클라이언트가 강제 종료될 수 있습니다.",
				func = function()
					GameTooltip:SetOwner(frame, "ANCHOR_NONE")
					GameTooltip:SetHyperlink("item:"..id..":0:0:0:0:0:0:0")
					GameTooltip:Hide()
					BlueItemInfo2:ScheduleEvent("BlueItemInfoReflash", "SetItemList", 1, BlueItemInfo2, BlueItemInfo2DB.category)
					BlueItemInfo2:CloseDropMenu()
					DropMenu:UnregisterMenu("BlueItemInfo2ItemFrameMenu")
				end,
			}}})
			DropMenu:OpenMenu("BlueItemInfo2ItemFrameMenu", "TOPLEFT", frame, "CENTER")
		end
	end
end

function BlueItemInfo2:CreateItemFrame(id)
	if id > BlueItemInfo2.data.itemframes then
		BlueItemInfo2.data.itemframes = id
	end
	if BlueItemInfo2.GUI["iframe"..id] then
		return BlueItemInfo2.GUI["iframe"..id]
	end
	local frame = BlueItemInfo2.GUI
	local iframe = CreateFrame("Button", "BlueItemInfo2ItemFrame"..id, frame.scrollchild, "QuestItemTemplate")
	frame["iframe"..id] = iframe
	iframe:SetID(id)
	iframe.itemID = 0
	iframe.compItem = nil
	iframe.text = _G[iframe:GetName().."Name"]
	local highlight = iframe:CreateTexture(nil, "BACKGROUND")
	iframe.highlight = highlight
	highlight:SetWidth(102)
	highlight:SetHeight(37)
	highlight:SetPoint("CENTER", iframe:GetName().."NameFrame", "CENTER", 0, 0)
	iframe:RegisterForClicks("LeftButtonUp", "RightButtonUp")
	iframe:SetScript("OnEnter", iframeOnEnter)
	iframe:SetScript("OnLeave", iframeOnLeave)
	iframe:SetScript("OnUpdate", iframeOnUpdate)
	iframe:SetScript("OnClick", iframeOnClick)
	if id == 1 then
		iframe:SetPoint("TOPLEFT", frame.scrollchild, "TOPLEFT", 0, 0)
	elseif mod(id, 4) == 1 then
		iframe:SetPoint("TOP", frame["iframe"..(id - 4)], "BOTTOM", 0, -4)
	else
		iframe:SetPoint("LEFT", frame["iframe"..(id - 1)], "RIGHT", 2, 0)
	end
	return iframe
end

function BlueItemInfo2:CreateDropdownFrame(id)
	local frame = self.GUI
	local drop = CreateFrame("Button", nil, frame)
	drop:SetID(id)
	drop:SetWidth(206)
	drop:SetHeight(24)
	drop:SetBackdrop(backdrop)
	drop:SetBackdropColor(0, 0, 0, 0.8)
	drop:EnableMouseWheel()
	drop:SetScript("OnEnter", function() drop:SetBackdropColor(1, 0, 0, 0.8) end)
	drop:SetScript("OnLeave", function() drop:SetBackdropColor(0, 0, 0, 0.8) end)
	drop:SetScript("OnMouseWheel", function() self:ScrollCategory(drop:GetID(), arg1) end)
	local text = drop:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	drop.text = text
	text:SetPoint("CENTER", drop, "CENTER", -10, 1)
	text:SetTextColor(1, 1, 1)
	drop:SetScript("OnClick", function()
		if DropMenu:IsOpen("BlueItemInfo2Menu"..id) then
			PlaySound("igMainMenuOptionCheckBoxOff")
			BlueItemInfo2:CloseDropMenu()
		elseif drop.text:GetText() ~= "" then
			local id = tonumber(drop:GetID())
			local menu = nil
			if id == 1 then
				menu = self.menu
			elseif id == 2 then
				menu = self.menu.args[frame.drop1.code]
			elseif id == 3 then
				menu = self.menu.args[frame.drop1.code].args[frame.drop2.code]
			end
			if menu and menu.args then
				PlaySound("igMainMenuOptionCheckBoxOn")
				DropMenu:RegisterMenu("BlueItemInfo2Menu"..id, menu)
				DropMenu:OpenMenu("BlueItemInfo2Menu"..id, "TOPLEFT", drop, "BOTTOMLEFT", 0, 0, nil, true)
			else
				BlueItemInfo2:CloseDropMenu()
			end
		else
			BlueItemInfo2:CloseDropMenu()
		end
	end)
	local dn = CreateFrame("Button", nil, drop)
	drop.down = dn
	dn:SetWidth(20)
	dn:SetHeight(20)
	dn:SetPoint("RIGHT", drop, "RIGHT", -2, 0)
	dn:SetNormalTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Up")
	dn:SetPushedTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Down")
	dn:SetDisabledTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Disabled")
	dn:SetHighlightTexture("Interface\\Buttons\\UI-Common-MouseHilight", "ADD")
	dn:SetScript("OnClick", function() self:ScrollCategory(drop:GetID(), -1) end)
	local up = CreateFrame("Button", nil, drop)
	drop.up = up
	up:SetWidth(20)
	up:SetHeight(20)
	up:SetPoint("RIGHT", dn, "LEFT", 5, 0)
	up:SetNormalTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollUp-Up")
	up:SetPushedTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollUp-Down")
	up:SetDisabledTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollUp-Disabled")
	up:SetHighlightTexture("Interface\\Buttons\\UI-Common-MouseHilight", "ADD")
	up:SetScript("OnClick", function() self:ScrollCategory(drop:GetID(), 1) end)
	return drop
end

function BlueItemInfo2:MenuOnClick(code)
	PlaySound("igMainMenuOptionCheckBoxOff")
	BlueItemInfo2:CloseDropMenu()
	self:SetCategory(code)
end

function BlueItemInfo2:SetCategory(code)
	BlueItemInfo2:CloseDropMenu()
	if code then
		BlueItemInfo2DB.category = code
	else
		code = BlueItemInfo2DB.category
	end
	local ncode = self:GetCategory(code)
	local name = self:GetCategoryName(code)
	if not name then
		code = self.defalutCode
		BlueItemInfo2DB.category = self.defalutCode
		ncode = self:GetCategory(code)
		name = self:GetCategoryName(code)
	end
	local drop, pi, ni
	for i = 1, 3 do
		drop = self.GUI["drop"..i]
		drop.text:SetText(name[i] or "")
		drop.code = ncode[i]
		pi, ni = self:GetNextCategory(i, code)
		if pi or ni then drop:Enable() else drop:Disable() end
		if pi then drop.up:Enable() else drop.up:Disable() end
		if ni then drop.down:Enable() else drop.down:Disable() end
	end
	self:SetItemList(code)
end

function BlueItemInfo2:GetNextCategory(id, code)
	id = tonumber(id)
	code = code or BlueItemInfo2DB.category
	local ncode = self:GetCategory(code)
	local n = strfind(v36, ncode[id])
	local pi, ni, nc
	if id == 1 then
		ncode[2] = "0"
		ncode[3] = "0"
	elseif id == 2 then
		ncode[3] = "0"
	end
	for i = n - 1, 1, -1 do
		ncode[id] = strsub(v36, i, i)
		nc = ncode[1]..ncode[2]..ncode[3]
		if self.data.items[nc] or (strfind("ABC", ncode[1]) and self.data.categoryCode[nc]) then
			pi = nc
			break
		end
	end
	for i = n + 1, strlen(v36) do
		ncode[id] = strsub(v36, i, i)
		nc = ncode[1]..ncode[2]..ncode[3]
		if self.data.items[nc] or (strfind("ABC", ncode[1]) and self.data.categoryCode[nc]) then
			ni = nc
			break
		end
	end
	return pi, ni
end

function BlueItemInfo2:ScrollCategory(id, scv)
	id = tonumber(id)
	local pi, ni = self:GetNextCategory(id)
	PlaySound("igMainMenuOptionCheckBoxOn")
	if scv > 0 and pi then
		self:SetCategory(pi)
	elseif scv < 0 and ni then
		self:SetCategory(ni)
	end
end

function BlueItemInfo2:CreateItemTable()
	self.fullsorted = "/"
	local hitems = {}
	local codes, c
	for p, v in pairs(self.data.itemDB) do
		self.data.num = self.data.num + 1
		codes = self:GetItemValue(p)
		for i = 1, #(codes) do
			if codes[i][1] == "H" then
				hitems[codes[i][2]] = hitems[codes[i][2]] and (hitems[codes[i][2]].."/"..p) or p
			elseif codes[i][1] == "r" then
				hitems[codes[i][2]] = hitems[codes[i][2]] and (hitems[codes[i][2]].."/"..p) or p
			elseif codes[i][1] == "A" then
				c = strsplit("@", codes[i][2])
				self.data.items[c] = self.data.items[c] and (self.data.items[c] .."/"..p) or p
			elseif codes[i][1] == "O" and codes[i][2] and not(strfind(codes[i][2], "^@")) then
				c = strsplit("@", codes[i][2])
				self.data.items[c] = self.data.items[c] and (self.data.items[c] .."/"..p) or p
			elseif codes[i][1] == "F" and codes[i][2] and not(strfind(codes[i][2], "^@")) then
				c = strsplit("@", codes[i][2])
				self.data.items[c] = self.data.items[c] and (self.data.items[c] .."/"..p) or p
			elseif codes[i][1] == "J" and codes[i][2] and not(strfind(codes[i][2], "^@")) then
				c = strsplit("@", codes[i][2])
			elseif codes[i][1] == "Y" and codes[i][2] and not(strfind(codes[i][2], "^@")) then
				c = strsplit("@", codes[i][2])
				self.data.items[c] = self.data.items[c] and (self.data.items[c] .."/"..p) or p
			elseif codes[i][1] == "M" and codes[i][2] and not(strfind(codes[i][2], "^@")) then
				c = strsplit("@", codes[i][2])
				self.data.items[c] = self.data.items[c] and (self.data.items[c] .."/"..p) or p
			elseif codes[i][1] == "T" then
				c = strsplit("@", codes[i][2])
				self.data.items[c] = self.data.items[c] and (self.data.items[c] .."/"..p) or p
			elseif codes[i][1] == "Q" then
				c = strsplit("@", codes[i][2])
				self.data.items[c] = self.data.items[c] and (self.data.items[c] .."/"..p) or p
			elseif not(strfind("CXsn", codes[i][1] or "*")) then
				self.data.items[codes[i][2]] = self.data.items[codes[i][2]] and (self.data.items[codes[i][2]] .."/"..p) or p
			end
		end
	end
	for p, v in pairs(self.data.itemDB0 or {}) do
		self.data.num = self.data.num + 1
		codes = self:GetItemValue(p)
		for i = 1, #(codes) do
			if codes[i][1] == "H" then
				hitems[codes[i][2]] = hitems[codes[i][2]] and (hitems[codes[i][2]].."/"..p) or p
			elseif codes[i][1] == "r" then
				hitems[codes[i][2]] = hitems[codes[i][2]] and (hitems[codes[i][2]].."/"..p) or p
			elseif codes[i][1] == "A" then
				c = strsplit("@", codes[i][2])
				self.data.items[c] = self.data.items[c] and (self.data.items[c] .."/"..p) or p
			elseif codes[i][1] == "O" and codes[i][2] and not(strfind(codes[i][2], "^@")) then
				c = strsplit("@", codes[i][2])
				self.data.items[c] = self.data.items[c] and (self.data.items[c] .."/"..p) or p
			elseif codes[i][1] == "J" and codes[i][2] and not(strfind(codes[i][2], "^@")) then
				c = strsplit("@", codes[i][2])
				self.data.items[c] = self.data.items[c] and (self.data.items[c] .."/"..p) or p
			elseif codes[i][1] == "T" then
				c = strsplit("@", codes[i][2])
				self.data.items[c] = self.data.items[c] and (self.data.items[c] .."/"..p) or p
			elseif codes[i][1] == "Q" then
				c = strsplit("@", codes[i][2])
				self.data.items[c] = self.data.items[c] and (self.data.items[c] .."/"..p) or p
			elseif not(strfind("CXsn", codes[i][1] or "*")) then
				self.data.items[codes[i][2]] = self.data.items[codes[i][2]] and (self.data.items[codes[i][2]] .."/"..p) or p
			end
		end
	end
	for p, v in pairs(self.data.itemDB1 or {}) do
		self.data.num = self.data.num + 1
		codes = self:GetItemValue(p)
		for i = 1, #(codes) do
			if codes[i][1] == "H" then
				hitems[codes[i][2]] = hitems[codes[i][2]] and (hitems[codes[i][2]].."/"..p) or p
			elseif codes[i][1] == "r" then
				hitems[codes[i][2]] = hitems[codes[i][2]] and (hitems[codes[i][2]].."/"..p) or p
			elseif codes[i][1] == "A" then
				c = strsplit("@", codes[i][2])
				self.data.items[c] = self.data.items[c] and (self.data.items[c] .."/"..p) or p
			elseif codes[i][1] == "O" and codes[i][2] and not(strfind(codes[i][2], "^@")) then
				c = strsplit("@", codes[i][2])
				self.data.items[c] = self.data.items[c] and (self.data.items[c] .."/"..p) or p
			elseif codes[i][1] == "J" and codes[i][2] and not(strfind(codes[i][2], "^@")) then
				c = strsplit("@", codes[i][2])
				self.data.items[c] = self.data.items[c] and (self.data.items[c] .."/"..p) or p
			elseif codes[i][1] == "T" then
				c = strsplit("@", codes[i][2])
				self.data.items[c] = self.data.items[c] and (self.data.items[c] .."/"..p) or p
			elseif codes[i][1] == "Q" then
				c = strsplit("@", codes[i][2])
				self.data.items[c] = self.data.items[c] and (self.data.items[c] .."/"..p) or p
			elseif not(strfind("CXsn", codes[i][1] or "*")) then
				self.data.items[codes[i][2]] = self.data.items[codes[i][2]] and (self.data.items[codes[i][2]] .."/"..p) or p
			end
		end
	end
	for p, v in pairs(hitems) do
		self.data.items[p] = (self.data.items[p] or "").."|"..v
	end
	hitems = nil
end

do

local i1, i2, mainCate, id, unknown, uk, item1, item2

function BlueItemInfo2:SetItemList(code)
	self.GUI.scrollframe:SetVerticalScroll(0)
	if self.data.items[code] then
		i1, i2 = strsplit("|", self.data.items[code])
		if strsub(self.data.items[code], 1, 1) == "|" then
			i1, i2 = nil, strsub(self.data.items[code], 2)
		end
		mainCate = strsub(code, 1, 1)
		id, unknown, uk = 1, 0
		item1, item2 = i1 and { strsplit("/", i1) } or {}, i2 and { strsplit("/", i2) } or {}
		if BlueItemInfo2DB.sort and not(strfind(self.fullsorted, "/"..code.."/")) then
			if i1 then
				item1, uk = self:SortItemTable(item1)
				unknown = unknown + uk
			end
			if i2 then
				item2, uk = self:SortItemTable(item2)
				unknown = unknown + uk
			end
			if unknown == 0 then
				if i1 and i2 then
					self.data.items[code] = table.concat(item1, "/").."|"..table.concat(item2, "/")
				elseif i1 then
					self.data.items[code] = table.concat(item1, "/")
				elseif i2 then
					self.data.items[code] = "|"..table.concat(item2, "/")
				end
				self.fullsorted = self.fullsorted..code.."/"
			end
		end
		if i1 then
			for i = 1, #(item1) do
				local it = tonumber(item1[i])
				if strfind(self:GetItemRealText(it) or "*", "B_"..code) then
					self:SetItemFrame(id, it, 0, 0.8, 0)
				else
					self:SetItemFrame(id, it)
				end
				id = id + 1
			end
		end
		if i2 then
			for i = 1, #(item2) do
				self:SetItemFrame(id, tonumber(item2[i]), 1, 0, 0)
				id = id + 1
			end
		end
		self:HideItemFrame(id - 1)
	else
		self:HideItemFrame(0)
	end
	i1, i2, mainCate, id, unknown, uk, item1, item2 = nil
end

local iframe, itemName, itemColorName, itemLink, itemTexture

function BlueItemInfo2:SetItemFrame(id, itemID, r, g, b)
	iframe = self.GUI["iframe"..id] or self:CreateItemFrame(id)
	itemName, itemColorName, itemLink, itemTexture = self:GetItemInfo(itemID)
	SetItemButtonTexture(iframe, itemTexture)
	iframe.itemID = itemID
	iframe.compItem = nil
	if itemName then
		iframe.text:SetText(itemColorName)
		SetItemButtonTextureVertexColor(iframe, 1, 1, 1)
	else
		iframe.text:SetText("|cffffffff미확인 아이템\nID "..iframe.itemID)
		if itemTexture == "Interface\\Icons\\INV_Misc_QuestionMark" then
			SetItemButtonTextureVertexColor(iframe, 1, 1, 1)
		else
			SetItemButtonTextureVertexColor(iframe, 1, 0.2, 0.2)
		end
	end
	iframe:Show()
	if r and g and b then
		iframe.highlight:SetGradientAlpha("VERTICAL", r * 0.6, g * 0.6, b * 0.6, 1, r, g, b, 1)
		iframe.highlight:SetTexture(r, g, b, 0.4)
		iframe.highlight:Show()
	else
		iframe.highlight:Hide()
	end
	iframe, itemName, itemColorName, itemLink, itemTexture = nil
end

function BlueItemInfo2:HideItemFrame(n)
	for i = n + 1, self.data.itemframes do
		self.GUI["iframe"..i]:Hide()
	end
	if n == 0 then
		self.GUI.nolist:Show()
	else
		self.GUI.nolist:Hide()
	end
end

end