local addOnName = GetAddOnDependencies(...)
local texturePath = "Interface\\AddOns\\"..(...).."\\Texture\\"
local BII3 = _G[addOnName]

local _G = _G
local ceil = _G.math.ceil
local tinsert = _G.table.insert
local sort = _G.table.sort
local wipe = _G.table.wipe
local GetItemCount = _G.GetItemCount
local IsAltKeyDown = _G.IsAltKeyDown
local IsShiftKeyDown = _G.IsShiftKeyDown
local IsControlKeyDown = _G.IsControlKeyDown
local IsModifiedClick = _G.IsModifiedClick
local items, buttons, heroicOffset, offset, displayNum = {}, {}, 0
local normal, heroic, category1, category2, category3, code1, code2, code3, currentCode, c1, c2, c3

local function setStatus(button, step, status)
	if step < 0 then
		button.prevCode = status
		if status then
			button.up:Enable()
		else
			button.up:Disable()
		end
	else
		button.nextCode = status
		if status then
			button.down:Enable()
		else
			button.down:Disable()
		end
	end
end

local function find1(first, last, step)
	for i = first, last, step do
		c1 = BII3.codeList:sub(i, i)
		if BII3.itemList[c1.."**"] then
			for j = BII3.codeListZero, BII3.codeListLen do
				c2 = c1..BII3.codeList:sub(j, j)
				if BII3.itemList[c2.."*"] then
					for k = BII3.codeListZero, BII3.codeListLen do
						c3 = c2..BII3.codeList:sub(k, k)
						if BII3.itemList[c3] then
							return setStatus(BII3.dropdownButtons[1], step, c3)
						end
					end
				end
			end
		end
	end
	setStatus(BII3.dropdownButtons[1], step, nil)
end

local function find2(first, last, step)
	for i = first, last, step do
		c1 = code1..BII3.codeList:sub(i, i)
		if BII3.itemList[c1.."*"] then
			for j = BII3.codeListZero, BII3.codeListLen do
				c2 = c1..BII3.codeList:sub(j, j)
				if BII3.itemList[c2] then
					return setStatus(BII3.dropdownButtons[2], step, c2)
				end
			end
		end
	end
	setStatus(BII3.dropdownButtons[2], step, nil)
end

local function find3(first, last, step)
	for i = first, last, step do
		c1 = code1..code2..BII3.codeList:sub(i, i)
		if BII3.itemList[c1] then
			return setStatus(BII3.dropdownButtons[3], step, c1)
		end
	end
	setStatus(BII3.dropdownButtons[3], step, nil)
end

local function addItemTable(item, ...)
	item = tonumber(item)
	tinsert(items, item)
	if ... then
		addItemTable(...)
	end
end

local function updateList()
	BII3:SortItem(currentCode)
	normal, heroic = ("_"):split(BII3.itemList[currentCode])
	wipe(items)
	if normal and normal ~= "" then
		addItemTable(nil, ("/"):split(normal))
	end
	heroicOffset = #items + 1
	if heroic and heroic ~= "" then
		addItemTable(true, ("/"):split(heroic))
	end
	normal, heroic = nil
	BII3:UpdateItemList()
end

function BII3:Update(force)
	if self.db.code ~= currentCode then
		self:CloseDropDownMenu()
		currentCode = self.db.code
		code1, code2, code3 = currentCode:match("(.)(.)(.)")
		category1, category2, category3 = BII3:GetCategoryName(currentCode)
		if self.dropdownButtons[1].code ~= code1 then
			self.dropdownButtons[1].code = code1
			self.dropdownButtons[1]:SetText(self:ClearColor(category1))
			find1(self.codeList:find(code1) - 1, 1, -1)
			find1(self.codeList:find(code1) + 1, self.codeListLen, 1)
		end
		if self.dropdownButtons[2].code ~= (code1..code2) then
			self.dropdownButtons[2].code = code1..code2
			self.dropdownButtons[2]:SetText(self:ClearColor(category2):gsub("^오리지널 ", "") or nil)
			self.dropdownButtons[2].key = code1
			find2(self.codeList:find(code2) - 1, self.codeListZero, -1)
			find2(self.codeList:find(code2) + 1, self.codeListLen, 1)
		end
		if category3 then
			self.dropdownButtons[3]:SetText(self:ClearColor(category3))
			self.dropdownButtons[3].key = code1..code2
			self.dropdownButtons[3]:Enable()
			find3(self.codeList:find(code3) - 1, self.codeListZero, -1)
			find3(self.codeList:find(code3) + 1, self.codeListLen, 1)
		else
			self.dropdownButtons[3]:SetText(nil)
			self.dropdownButtons[3].key = nil
			self.dropdownButtons[3]:Disable()
			self.dropdownButtons[3].prevCode, self.dropdownButtons[3].nextCode = nil
			self.dropdownButtons[3].up:Disable()
			self.dropdownButtons[3].down:Disable()
		end
		c1, c2, c3, code1, code2, code3, category1, category2, category3 = nil
		updateList(force)
		self.container.scrollBar:SetValue(0)
	elseif force then
		updateList(force)
	end
end

function BII3:MODIFIER_STATE_CHANGED()
	if IsModifiedClick("DRESSUP") then
		ShowInspectCursor()
	else
		ResetCursor()
	end
	if IsModifiedClick("COMPAREITEMS") then
		GameTooltip_ShowCompareItem(GameTooltip, 1)
	end
end

local function buttonOnClick(self, button)
	if BII3:IsItem(self.id) then
		if button == "LeftButton" then
			BII3:CloseDropDownMenu()
			if IsControlKeyDown() and IsShiftKeyDown() then
				BII3:AddMemo(self.id)
			elseif IsAltKeyDown() then
				BII3:AddFavorite(self.id)
			elseif IsModifiedClick() then
				HandleModifiedItemClick(BII3:GetItemLink(self.id))
			else
				SetItemRef(BII3:GetItemSimpleLink(self.id), BII3:GetItemLink(self.id), button)
			end
		elseif UIDROPDOWNMENU_OPEN_MENU == BII3.itemDropdown then
			if UIDROPDOWNMENU_MENU_VALUE == self.id then
				UIDROPDOWNMENU_MENU_VALUE = nil
				CloseDropDownMenus(1)
			else
				ToggleDropDownMenu(1, self.id, BII3.itemDropdown, "cursor")
			end
		else
			ToggleDropDownMenu(1, self.id, BII3.itemDropdown, "cursor")
		end
	else
		BII3:CloseDropDownMenu()
	end
end

local function buttonStopUpdate(self)
	self.timer = nil
	self:SetScript("OnUpdate", nil)
end

local itemName, itemRarity

local function buttonUpdateItemName(self)
	if self.noitem then
		itemName, _, itemRarity = GetItemInfo(self.id)
		if itemName then
			BII3.itemNameDB[self.id] = itemRarity.."|"..itemName
			itemName, itemRarity = nil
			self.noitem = nil
			self.name:SetText(BII3:GetItemColorName(self.id))
		end
	end
end

local function buttonOnUpdate(self, timer)
	self.timer = self.timer + timer
	if self.timer > 0.25 then
		GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT", -150, 0)
		GameTooltip:SetHyperlink("item:"..self.id)
		GameTooltip:Show()
		if GetItemInfo(self.id) then
			buttonStopUpdate(self)
			buttonUpdateItemName(self)
		else
			self.timer = 0
		end
	end
end

local function buttonOnEnter(self)
	GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT", -150, 0)
	if self.id > 0 then
		GameTooltip:SetHyperlink("item:"..self.id)
		BII3:MODIFIER_STATE_CHANGED()
		BII3:RegisterEvent("MODIFIER_STATE_CHANGED")
		if GetItemInfo(self.id) then
			buttonStopUpdate(self)
			buttonUpdateItemName(self)
		else
			self.timer = 0
			self:SetScript("OnUpdate", buttonOnUpdate)
		end
	elseif self.id < 0 then
		buttonStopUpdate(self)
		GameTooltip:SetHyperlink("spell:"..-self.id)
	end
	GameTooltip:Show()
end

local function buttonOnLeave(self)
	buttonStopUpdate(self)
	BII3:UnregisterEvent("MODIFIER_STATE_CHANGED")
	GameTooltip:Hide()
	ResetCursor()
end

local function createItemButton(id)
	if not buttons[id] then
		buttons[id] = CreateFrame("Button", addOnName.."ItemButton"..id, BII3.container.scrollChild, "LargeItemButtonTemplate")
		buttons[id]:SetID(id)
		buttons[id]:RegisterForClicks("LeftButtonUp", "RightButtonUp")
		buttons[id].name = _G[addOnName.."ItemButton"..id.."Name"]
		buttons[id].name:SetText(UNKNOWN)
		buttons[id].name:ClearAllPoints()
		buttons[id].name:SetPoint("TOPLEFT", addOnName.."ItemButton"..id.."NameFrame", 14, -10)
		buttons[id].name:SetPoint("BOTTOMRIGHT", addOnName.."ItemButton"..id.."NameFrame", -17, 12)
		buttons[id].icon = _G[addOnName.."ItemButton"..id.."IconTexture"]
		buttons[id].icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark")
		buttons[id].border = buttons[id]:CreateTexture(nil, "ARTWORK")
		buttons[id].border:SetTexture(texturePath.."IconBorder")
		buttons[id].border:SetAllPoints(buttons[id].icon)
		buttons[id].border:SetAlpha(0.5)
		buttons[id].border:Hide()
		buttons[id].highlight = buttons[id]:CreateTexture(nil, "BACKGROUND")
		buttons[id].highlight:SetGradientAlpha("VERTICAL", 0.6, 0, 0, 1, 1, 0, 0, 1)
		buttons[id].highlight:SetTexture(1, 0, 0, 0.4)
		buttons[id].highlight:SetPoint("CENTER", _G[addOnName.."ItemButton"..id.."NameFrame"], 0, 0)
		buttons[id].highlight:SetSize(102, 37)
		buttons[id].itemChecked = buttons[id]:CreateTexture(nil, "OVERLAY")
		buttons[id].itemChecked:SetTexture("Interface\\RaidFrame\\ReadyCheck-Ready")
		buttons[id].itemChecked:SetSize(32, 24)
		buttons[id].itemChecked:SetPoint("CENTER", buttons[id].icon, 0, 0)
		buttons[id]:SetScript("OnClick", buttonOnClick)
		buttons[id]:SetScript("OnEnter", buttonOnEnter)
		buttons[id]:SetScript("OnLeave", buttonOnLeave)
		if id == 1 then
			buttons[id]:SetPoint("TOPLEFT", 0, 0)
			BII3.container.buttons[1] = buttons[id]
		elseif id % 4 == 1 then
			buttons[id]:SetPoint("TOPLEFT", buttons[id - 4], "BOTTOMLEFT", 0, -2)
			BII3.container.buttons[ceil(id / 4)] = buttons[id]
		else
			buttons[id]:SetPoint("LEFT", buttons[id - 1], "RIGHT", 1, 0)
		end
	end
end

local function clearItemButton(id)
	buttons[id].id = nil
	buttons[id].noitem = nil
	buttons[id].name:SetText()
	buttons[id]:Hide()
end

function BII3:GetNumDisplayList()
	return ceil(self.container:GetHeight() / self.container.buttonHeight + 1) * 4
end

function BII3:UpdateItemList()
	if BII3:IsShown() then
		BII3.container.displayNum = BII3:GetNumDisplayList()
		offset = HybridScrollFrame_GetOffset(BII3.container) * 4
		for i = 1, BII3.container.displayNum do
			offset = offset + 1
			if offset > #items then
				if buttons[i] then
					clearItemButton(i)
				end
			else
				createItemButton(i)
				buttons[i].id = items[offset]
				buttons[i].icon:SetTexture(BII3:GetItemIcon(items[offset]))
				buttons[i].name:SetText(BII3:GetItemColorName(items[offset]))
				buttons[i].itemChecked:Hide()
				if buttons[i].id > 0 and GetItemCount(buttons[i].id) > 0 then
					buttons[i].itemChecked:SetDesaturated(nil)
					buttons[i].itemChecked:Show()
				elseif BII3:IsFavorite(buttons[i].id) then
					buttons[i].itemChecked:SetDesaturated(true)
					buttons[i].itemChecked:Show()
				else
					buttons[i].itemChecked:Hide()
				end
				if buttons[i].id > 0 and not BII3:IsItem(items[offset]) then
					buttons[i].noitem = true
				else
					buttons[i].noitem = nil
				end
				if heroicOffset > offset then
					buttons[i].highlight:Hide()
				else
					buttons[i].highlight:Show()
				end
				buttons[i]:Show()
			end
		end
		for i = BII3.container.displayNum + 1, #buttons do
			clearItemButton(i)
		end
		HybridScrollFrame_Update(BII3.container, ceil(#items / 4) * BII3.container.buttonHeight, BII3.container:GetHeight())
	end
end

BII3.container.update = BII3.UpdateItemList
BII3.container.buttons = {}
BII3.container.buttonHeight = (QuestProgressItem1:GetHeight() + 2)
BII3.container.stepSize = BII3.container.buttonHeight * 2.5
