local _G = _G
local type = _G.type
local pairs = _G.pairs
local ipairs = _G.ipairs
local select = _G.select
local tonumber = _G.tonumber
local tinsert = _G.table.insert
local GetSpellInfo = _G.GetSpellInfo

local LDM = LibStub("LibDropMenu-2.0")

local statFilter = {
	["힘"] = true,
	["민첩성"] = true,
	["체력"] = true,
	["지능"] = true,
	["정신력"] = true,
	["모든 능력치"] = { "힘", "민첩성", "체력", "지능", "정신력" },
	["비전 저항력"] = true,
	["화염 저항력"] = true,
	["자연 저항력"] = true,
	["냉기 저항력"] = true,
	["암흑 저항력"] = true,
	["최대 생명력"] = "생명력",
	["모든 저항력"] = { "비전 저항력", "화염 저항력", "자연 저항력", "냉기 저항력", "암흑 저항력" },
	["^전투력"] = { "전투력", "원거리 전투력" },
	["\n전투력"] = { "전투력", "원거리 전투력" },
	["근접 전투력"] = "전투력",
	["원거리 전투력"] = true,
	["주문력"] = { "주문 공격력", "주문 치유량" },
	["5초당 마나 회복량"] = { "5초당 마나 회복량", "시전 중 마나 회복량" },
	["공격력"] = "물리 공격력 배율",
	["생명력"] = true,
	["^치명타 적중률"] = { "치명타율", "원거리 치명타율" },
	["\n치명타 적중률"] = { "치명타율", "원거리 치명타율" },
	["근접 치명타 적중률"] = "치명타율",
	["원거리 치명타 적중률"] = "원거리 치명타율",
	["주문 극대화 적중률"] = "극대화율",
	["근접 공격 속도"] = "공격 속도 배율",
	["원거리 공격 속도"] = "원거리 공격 속도 배율",
	["^공격 속도"] = { "공격 속도 배율", "원거리 공격 속도 배율" },
	["\n공격 속도"] = { "공격 속도 배율", "원거리 공격 속도 배율" },
	["주문 시전 가속도"] = "주문 가속도",
	["근접 공격 가속도"] = "가속도",
	["원거리 공격 가속도"] = "원거리 가속도",
	["^가속도"] = { "가속도", "원거리 가속도", "주문 가속도" },
	["\n가속도"] = { "가속도", "원거리 가속도", "주문 가속도" },
	["^숙련도"] = "숙련도",
	["\n숙련도"] = "숙련도",
	["^적중도"] = { "적중도", "원거리 적중도", "주문 적중도" },
	["\n적중도"] = { "적중도", "원거리 적중도", "주문 적중도" },
	["방어 숙련도"] = true,
	["치명타 및 주문 극대화 적중도"] = { "치명타 및 주문 극대화 적중도", "주문 극대화 적중도", "원거리 치명타 적중도" },
	["회피 숙련도"] = true,
	["방패 피해 방어량"] = true,
	["무기 막기 숙련도"] = true,
	["방어구 관통력"] = true,
	["주문 관통력"] = true,
	["회피 확률"] = "회피율",
	["무기 막기 확률"] = "무기 막기",
	["방패 막기 확률"] = "방패 막기",
	["장비 착용으로 인한 방어도"] = "아이템 방어도",
	["^방어도"] = "방어도",
	["\n방어도"] = "방어도",
}
local isLastCalcSpec = { ["전투력"] = true, ["원거리 전투력"] = true, ["5초당 마나 회복량"] = true, ["시전 중 마나 회복량"] = true, ["생명력"] = true, ["방어도"] = true, ["방패 피해 방어량"] = true, ["주문 공격력"] = true, ["주문 치유량"] = true }
local isLastCalcSpecMulti = { ["전투력"] = true, ["원거리 전투력"] = true, ["주문 공격력"] = true, ["주문 치유량"] = true }
local buffList = InvenSimulatorUI.database.buffList
local buffTooltipText = InvenSimulatorUI.database.buffDB
local buffIcon = InvenSimulatorUI.database.buffIcon
local linkedBuff = InvenSimulatorUI.database.linkedBuff
local buffStatusFunc = {}
local isClassBuff = {}
local startUserBuff = #buffList + 1
local buffMenu

function InvenSimulatorUI:UpdateClassBuffText(buff, text)
	if isClassBuff[buff] and buffTooltipText[buff] ~= text then
		buffTooltipText[buff] = text
		self:SetEnableBuff(buff, self.db.buffs[buff])
	end
end

function InvenSimulatorUI:CreateBuffFrame()
	if self.InitRaceBuff then
		local name, spell, text = self:InitRaceBuff()
		if name and not buffTooltipText[name] then
			isClassBuff[name] = true
			tinsert(buffList, name)
			buffIcon[name] = spell
			buffTooltipText[name] = text
		end
	end
	if self.InitClassBuff then
		local numBuff, classBuff = self:InitClassBuff()
		for i = 1, numBuff * 4, 4 do
			if classBuff[i] and not buffTooltipText[classBuff[i]] then
				isClassBuff[classBuff[i]] = true
				tinsert(buffList, classBuff[i])
				buffIcon[classBuff[i]] = classBuff[i + 1]
				buffTooltipText[classBuff[i]] = classBuff[i + 2]
				buffStatusFunc[#buffList] = classBuff[i + 3]
			end
		end
	end
	if self.CheckItemBuffStatus and self.CheckItemEnchantBuffStatus then
		for i = 1, 19 do
			isClassBuff[i] = true
			buffIcon[i] = 0
			tinsert(buffList, i)
			buffStatusFunc[#buffList] = self.CheckItemBuffStatus
			buffTooltipText[i] = ""
			isClassBuff["enchant"..i] = true
			buffIcon["enchant"..i] = 0
			tinsert(buffList, "enchant"..i)
			buffStatusFunc[#buffList] = self.CheckItemEnchantBuffStatus
			buffTooltipText["enchant"..i] = ""
		end
	end
	for p, v in pairs(buffIcon) do
		buffIcon[p] = select(3, GetSpellInfo(v)) or "Interface\\Icons\\Temp"
	end
	if self.CheckDopingStatus then
		tinsert(buffList, "전투 비약")
		isClassBuff["전투 비약"] = true
		buffIcon["전투 비약"] = "Interface\\Icons\\INV_Alchemy_Potion_02"
		buffTooltipText["전투 비약"] = ""
		buffStatusFunc[#buffList] = self.CheckDopingStatus
		tinsert(buffList, "강화 비약")
		isClassBuff["강화 비약"] = true
		buffIcon["강화 비약"] = "Interface\\Icons\\INV_Alchemy_Potion_03"
		buffTooltipText["강화 비약"] = ""
		buffStatusFunc[#buffList] = self.CheckDopingStatus
		tinsert(buffList, "음식")
		isClassBuff["음식"] = true
		buffIcon["음식"] = "Interface\\Icons\\Spell_Misc_Food"
		buffTooltipText["음식"] = ""
		buffStatusFunc[#buffList] = self.CheckDopingStatus
		tinsert(buffList, "물약")
		isClassBuff["물약"] = true
		buffIcon["물약"] = "Interface\\Icons\\INV_Alchemy_Elixir_Empty"
		buffTooltipText["물약"] = ""
		buffStatusFunc[#buffList] = self.CheckDopingStatus
	end
	if self.InitExtraBuff then
		self:InitExtraBuff(buffList, buffTooltipText, buffIcon, isClassBuff, buffStatusFunc)
	end
	for p, v in pairs(InvenSimulatorCharDB.buffs) do
		if not isClassBuff[p] then
			if type(buffTooltipText[p]) == "table" then
				if not buffTooltipText[p][v] then
					InvenSimulatorCharDB.buffs[p] = nil
				end
			elseif type(buffTooltipText[p]) == "string" then
				if v ~= 0 then
					InvenSimulatorCharDB.buffs[p] = 0
				end
			else
				InvenSimulatorCharDB.buffs[p] = nil
			end
		end
	end
	local left = self:CreateTexture(nil, "BACKGROUND")
	left:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ClassSkillsTab-L2")
	left:SetPoint("TOPLEFT", self, "BOTTOMLEFT", 0, 2)
	left:SetWidth(14)
	left:SetHeight(110)
	left:SetTexCoord(0.04296875, 0.09765625, 0.72, 0.775)
	local right = self:CreateTexture(nil, "BACKGROUND")
	right:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ClassSkillsTab-R2")
	right:SetPoint("TOPRIGHT", self, "BOTTOMRIGHT", 0, 2)
	right:SetWidth(14)
	right:SetHeight(110)
	right:SetTexCoord(0.6484375, 0.7578125, 0.72, 0.775)
	local bottomLeft = self:CreateTexture(nil, "BACKGROUND")
	bottomLeft:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ClassSkillsTab-L2")
	bottomLeft:SetPoint("TOPLEFT", left, "BOTTOMLEFT")
	bottomLeft:SetWidth(14)
	bottomLeft:SetHeight(14)
	bottomLeft:SetTexCoord(0.04296875, 0.09765625, 0.775, 0.8296875)
	local bottomRight = self:CreateTexture(nil, "BACKGROUND")
	bottomRight:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ClassSkillsTab-R2")
	bottomRight:SetPoint("TOPRIGHT", right, "BOTTOMRIGHT")
	bottomRight:SetWidth(14)
	bottomRight:SetHeight(14)
	bottomRight:SetTexCoord(0.6484375, 0.7578125, 0.775, 0.8296875)
	local bottom = self:CreateTexture(nil, "BACKGROUND")
	bottom:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ClassSkillsTab-L2")
	bottom:SetPoint("TOPLEFT", bottomLeft, "TOPRIGHT")
	bottom:SetPoint("BOTTOMRIGHT", bottomRight, "BOTTOMLEFT")
	bottom:SetTexCoord(0.09765625, 0.1, 0.775, 0.8296875)
	local center = self:CreateTexture(nil, "BACKGROUND")
	center:SetTexture(0, 0, 0)
	center:SetPoint("TOPLEFT", left, "TOPRIGHT")
	center:SetPoint("BOTTOMRIGHT", right, "BOTTOMLEFT")
	self.buffFrame = CreateFrame("Frame", nil, self)
	self.buffFrame.left = left
	self.buffFrame.right = right
	self.buffFrame:EnableMouse(true)
	self.buffFrame:RegisterForDrag("LeftButton", "RightButton")
	self.buffFrame:SetPoint("TOPLEFT", center, "TOPLEFT", -10, 0)
	self.buffFrame:SetPoint("BOTTOMRIGHT", center, "BOTTOMRIGHT", 10, -10)
	self.buffFrame:SetScript("OnDragStart", function() InvenSimulatorUI:GetScript("OnDragStart")(InvenSimulatorUI) end)
	self.buffFrame:SetScript("OnDragStop", function() InvenSimulatorUI:GetScript("OnDragStop")(InvenSimulatorUI) end)
	self.buffFrame.SetHeight = function(self, height)
		height = height or 0
		self.left:SetHeight(110 + height)
		self.right:SetHeight(110 + height)
	end
	self.buffFrame.buff = {}
	local function buttonOnEnter(self)
		GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
		GameTooltip:AddLine(self.itemName or self.name)
		if self.itemName == "|cffa335ee죽음인도자의 의지|r" then
			if InvenSimulatorCharDB.buffs[self.name] then
				GameTooltip:AddLine(buffTooltipText[self.name], 1, 1, 1, 1)
			else
				GameTooltip:AddLine(buffTooltipText[self.name], 0.58, 0.58, 0.58, 1)
			end
			GameTooltip:AddLine("<클릭: 메뉴 열기>", 0, 1, 0)
		elseif self.status and (self.status == InvenSimulatorUI.CheckDopingStatus or self.status == InvenSimulatorUI.CheckIceCrownBuff) then
			if InvenSimulatorCharDB.buffs[self.name] then
				GameTooltip:AddLine(buffTooltipText[self.name], 1, 1, 1, 1)
			end
			GameTooltip:AddLine("<클릭: 메뉴 열기>", 0, 1, 0)
		elseif InvenSimulatorCharDB.buffs[self.name] then
			if type(buffTooltipText[self.name]) == "table" then
				GameTooltip:AddLine(buffTooltipText[self.name][InvenSimulatorCharDB.buffs[self.name]], 1, 1, 1, 1)
				GameTooltip:AddLine("<좌클릭: 비활성화>", 0, 1, 0)
				GameTooltip:AddLine("<우클릭: 메뉴 열기>", 0, 1, 0)
			else
				GameTooltip:AddLine(buffTooltipText[self.name], 1, 1, 1, 1)
				GameTooltip:AddLine("<클릭: 비활성화>", 0, 1, 0)
			end
		elseif type(buffTooltipText[self.name]) == "table" then
			GameTooltip:AddLine(buffTooltipText[self.name][buffTooltipText[self.name].max or 0], 0.58, 0.58, 0.58, 1)
			GameTooltip:AddLine("<좌클릭: 최고 단계 활성화>", 0, 1, 0)
			GameTooltip:AddLine("<우클릭: 메뉴 열기>", 0, 1, 0)
		else
			GameTooltip:AddLine(buffTooltipText[self.name], 0.58, 0.58, 0.58, 1)
			GameTooltip:AddLine("<클릭: 활성화>", 0, 1, 0)
		end
		GameTooltip:Show()
	end
	local function buttonOnClick(self, button)
		if self.itemName == "|cffa335ee죽음인도자의 의지|r" then
			InvenSimulatorUI:OpenDeathbringersWillMenu(self)
		elseif self.status and self.status == InvenSimulatorUI.CheckDopingStatus then
			InvenSimulatorUI:OpenDopingMenu(self)
		elseif self.status and self.status == InvenSimulatorUI.CheckIceCrownBuff then
			InvenSimulatorUI:OpenIceCrownBuffMenu(self)
		elseif button == "RightButton" and type(buffTooltipText[self.name]) == "table" then
			if LDM:IsOpen("InvenSimulatorBuffMenu") then
				LDM:CloseMenu(1)
			else
				InvenSimulatorUI:OpenBuffMenu(self)
			end
		else
			if InvenSimulatorCharDB.buffs[self.name] then
				InvenSimulatorUI:SetEnableBuff(self.name, nil)
			elseif type(buffTooltipText[self.name]) == "table" then
				InvenSimulatorUI:SetEnableBuff(self.name, buffTooltipText[self.name].max)
			else
				InvenSimulatorUI:SetEnableBuff(self.name, 0)
			end
			InvenSimulatorUI:Calculate()
			buttonOnEnter(self)
			LDM:CloseMenu(1)
		end
	end
	for p, v in ipairs(buffList) do
		self.buffFrame.buff[v] = CreateFrame("Button", "InvenSimulatorBuffButton"..p, self.buffFrame)
		self.buffFrame.buff[v]:SetID(p)
		self.buffFrame.buff[v]:SetWidth(24)
		self.buffFrame.buff[v]:SetHeight(24)
		self.buffFrame.buff[v]:SetNormalTexture(buffIcon[v] or "Interface\\Icons\\Temp")
		self.buffFrame.buff[v].icon = self.buffFrame.buff[v]:GetNormalTexture()
		self.buffFrame.buff[v].icon:SetTexCoord(0.07, 0.93, 0.07, 0.93)
		self.buffFrame.buff[v]:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square")
		self.buffFrame.buff[v]:RegisterForClicks("LeftButtonUp", "RightButtonUp")
		self.buffFrame.buff[v]:SetScript("OnEnter", buttonOnEnter)
		self.buffFrame.buff[v]:SetScript("OnLeave", GameTooltip_Hide)
		self.buffFrame.buff[v]:SetScript("OnClick", buttonOnClick)
		self.buffFrame.buff[v].name = v
		self.buffFrame.buff[v].status = buffStatusFunc[p]
		self.buffFrame.buff[v].addSpec = {}
		self.buffFrame.buff[v].multiSpec = {}
		self:SetEnableBuff(v, self.db.buffs[v])
		if p == 1 then
			self.buffFrame.buff[v]:SetPoint("TOPLEFT", 12, -7)
		elseif mod(p, 12) == 1 then
			if not isClassBuff[v] then
				self.buffFrame.lastBuff = self.buffFrame.buff[v]
			end
			self.buffFrame.buff[v]:SetPoint("TOP", self.buffFrame.buff[buffList[p - 12] ], "BOTTOM", 0, -2)
		else
			self.buffFrame.buff[v]:SetPoint("LEFT", self.buffFrame.buff[buffList[p - 1] ], "RIGHT", 2, 0)
		end
	end
	self.buffFrame.needUpdate = true

	self.buffFrame.removeAllButton = CreateFrame("Button", "InvenSimulatorUIRemoveAllBuffs", self, "UIPanelButtonTemplate")
	self.buffFrame.removeAllButton:SetWidth(90)
	self.buffFrame.removeAllButton:SetHeight(20)
	self.buffFrame.removeAllButton:SetScale(0.9)
	self.buffFrame.removeAllButton:SetText("모든 버프 제거")
	self.buffFrame.removeAllButton:SetPoint("BOTTOM", self.buffFrame, "TOP", 0, -7)
	self.buffFrame.removeAllButton:SetScript("OnClick", function()
		for buff in pairs(InvenSimulatorUI.db.buffs) do
			InvenSimulatorUI:SetEnableBuff(buff, nil)
		end
		InvenSimulatorUI:Calculate()
		LDM:CloseMenu(1)
	end)
end

local menuList = {}
local menuGet = function(buff, value)
	return InvenSimulatorCharDB.buffs[buff] == value
end
local menuSet = function(_, buff, value)
	if value ~= InvenSimulatorCharDB.buffs[buff] then
		InvenSimulatorCharDB.buffs[buff] = value
		InvenSimulatorUI:SetEnableBuff(buff, value)
		InvenSimulatorUI:Calculate()
	end
	LDM:CloseMenu(1)
end

function InvenSimulatorUI:OpenBuffMenu(button)
	if not buffMenu then
		buffMenu = { type = "group", args = {} }
		LDM:RegisterMenu("InvenSimulatorBuffMenu", buffMenu)
	end
	for p in pairs(buffTooltipText[button.name]) do
		if type(p) == "number" then
			tinsert(menuList, p)
		end
	end
	sort(menuList, function(a, b) return a > b end)
	tinsert(menuList, -1)
	for p, v in ipairs(menuList) do
		if not buffMenu.args[p] then
			buffMenu.args[p] = { type = "toggle", order = p, get = menuGet, set = menuSet }
		end
		buffMenu.args[p].arg1 = button.name
		buffMenu.args[p].hidden = nil
		if v == -1 then
			buffMenu.args[p].name = "없음"
			buffMenu.args[p].arg2 = nil
			buffMenu.args[p].desc = nil
			buffMenu.args[p].desc1 = nil
		else
			buffMenu.args[p].arg2 = v
			buffMenu.args[p].desc = button.name
			buffMenu.args[p].desc1 = buffTooltipText[button.name][v]
			if v == 0 then
				buffMenu.args[p].name = button.name
			elseif buffTooltipText[button.name].max ~= floor(buffTooltipText[button.name].max) then
				if v == floor(v) then
					buffMenu.args[p].name = button.name.."(연마 "..v.."/0)"
				else
					buffMenu.args[p].name = button.name.."(연마 "..v..")"
					buffMenu.args[p].name = buffMenu.args[p].name:gsub("%.", "/")
				end
			elseif button.name == "왕의 축복" then
				if v == 1 then
					buffMenu.args[p].name = "잊혀진 왕의 축복"
				else
					buffMenu.args[p].name = button.name
				end
			else
				buffMenu.args[p].name = button.name.."(연마 "..v..")"
			end
		end
	end
	for i = #menuList + 1, #buffMenu.args do
		buffMenu.args[i].hidden = true
	end
	for p in pairs(menuList) do
		menuList[p] = nil
	end
	LDM:OpenMenu("InvenSimulatorBuffMenu", "TOPLEFT", button, "TOPRIGHT")
end

local forceAddSpec = { ["근접 치명타 적중률"] = true, ["원거리 치명타 적중률"] = true, ["치명타 적중률"] = true, ["주문 극대화 적중률"] = true, ["무기 막기 확률"] = true, ["회피 확률"] = true, ["방패 막기 확률"] = true }

function InvenSimulatorUI:SetEnableBuff(buff, toggle)
	if self.buffFrame and self.buffFrame.buff[buff] then
		for p in pairs(self.buffFrame.buff[buff].addSpec) do
			self.buffFrame.buff[buff].addSpec[p] = nil
		end
		for p in pairs(self.buffFrame.buff[buff].multiSpec) do
			self.buffFrame.buff[buff].multiSpec[p] = nil
		end
		if self.buffFrame.buff[buff].status and self.buffFrame.buff[buff].status == self.CheckDopingStatus then
			if toggle then
				self.db.buffs[buff] = toggle
				toggle = buffTooltipText[self.buffFrame.buff[buff].name] or ""
			else
				self.db.buffs[buff] = nil
			end
		elseif self.buffFrame.buff[buff].status and self.buffFrame.buff[buff].status == self.CheckIceCrownBuff then
			if toggle then
				self.db.buffs[buff] = toggle
				toggle = buffTooltipText[self.buffFrame.buff[buff].name]
			else
				self.db.buffs[buff] = nil
				toggle = nil
			end
		elseif toggle then
			if type(buffTooltipText[self.buffFrame.buff[buff].name]) == "string" then
				if buff == 13 or buff == 14 or toggle == 0 then
					self.db.buffs[buff] = toggle
					toggle = buffTooltipText[self.buffFrame.buff[buff].name]
				else
					self.db.buffs[buff] = nil
					toggle = nil
				end
			elseif type(buffTooltipText[self.buffFrame.buff[buff].name]) == "table" and buffTooltipText[self.buffFrame.buff[buff].name][toggle] then
				self.db.buffs[buff] = toggle
				toggle = buffTooltipText[self.buffFrame.buff[buff].name][toggle]
			else
				self.db.buffs[buff] = nil
				toggle = nil
			end
		else
			self.db.buffs[buff] = nil
		end
		if toggle then
			self.buffFrame.buff[buff].enable = true
			self.buffFrame.buff[buff].icon:SetDesaturated(nil)
			self.buffFrame.buff[buff].icon:SetAlpha(1)
			local val, tar
			for p, v in pairs(statFilter) do
				val = tonumber(toggle:match(p.." (%d+)만큼 증가") or "")
				if val then
					tar = "addSpec"
				else
					val = tonumber(toggle:match(p.." (%d+)%%만큼 증가") or "")
					if forceAddSpec[p] then
						tar = "addSpec"
					elseif val then
						tar = "multiSpec"
						val = val / 100
					end
				end
				if val then
					if p == "공격력" and tar == "addSpec" then
						self.buffFrame.buff[buff][tar]["무기 공격력"] = val
					elseif type(v) == "string" then
						self.buffFrame.buff[buff][tar][v] = val
					elseif type(v) == "table" then
						for i = 1, #v do
							self.buffFrame.buff[buff][tar][v[i]] = val
						end
					else
						self.buffFrame.buff[buff][tar][p] = val
					end
				end
				val = tonumber(toggle:match(p.." (%d+)만큼 감소") or "")
				if val then
					tar = "addSpec"
				else
					val = tonumber(toggle:match(p.." (%d+)%%만큼 감소") or "")
					if forceAddSpec[p] then
						tar = "addSpec"
					elseif val then
						tar = "multiSpec"
						val = val / 100
					end
				end
				if val then
					if p == "공격력" and tar == "addSpec" then
						self.buffFrame.buff[buff][tar]["무기 공격력"] = -val
					elseif type(v) == "string" then
						self.buffFrame.buff[buff][tar][v] = -val
					elseif type(v) == "table" then
						for i = 1, #v do
							self.buffFrame.buff[buff][tar][v[i]] = -val
						end
					else
						self.buffFrame.buff[buff][tar][p] = -val
					end
				end
			end
			if buff == "방패 막기" then
				self.buffFrame.buff[buff].multiSpec["방패 피해 방어량"] = nil
			end
		else
			self.buffFrame.buff[buff].enable = nil
			self.buffFrame.buff[buff].icon:SetDesaturated(true)
			self.buffFrame.buff[buff].icon:SetAlpha(0.5)
		end
	end
end

local add, multi, maxValue, maxIdx = {}, {}

function InvenSimulatorUI:ApplyBuff()
	for buff in pairs(isClassBuff) do
		if self.buffFrame.buff[buff].status then
			if self.buffFrame.buff[buff]:IsShown() then
				if not self.buffFrame.buff[buff].status(self.buffFrame.buff[buff]) then
					self.buffFrame.buff[buff]:Hide()
					self.buffFrame.needUpdate = true
				end
			elseif self.buffFrame.buff[buff].status(self.buffFrame.buff[buff]) then
				self.buffFrame.buff[buff]:Show()
				self.buffFrame.needUpdate = true
			end
		end
	end
	if self.buffFrame.needUpdate then
		local line = 0
		local showIndex = startUserBuff - 1
		local prev = self.buffFrame.buff[buffList[startUserBuff - 1]]
		local nextBuff = self.buffFrame.lastBuff
		for i = startUserBuff, #buffList do
			if self.buffFrame.buff[buffList[i]]:IsShown() then
				showIndex = showIndex + 1
				self.buffFrame.buff[buffList[i]]:ClearAllPoints()
				if mod(showIndex, 12) == 1 then
					self.buffFrame.buff[buffList[i]]:SetPoint("TOP", nextBuff, "BOTTOM", 0, -2)
					nextBuff = self.buffFrame.buff[buffList[i]]
					line = line + 1
				else
					self.buffFrame.buff[buffList[i]]:SetPoint("LEFT", prev, "RIGHT", 2, 0)
				end
				prev = self.buffFrame.buff[buffList[i]]
			end
		end
		self.buffFrame:SetHeight(26 * line)
	end
	for p in pairs(add) do
		for v in pairs(add[p]) do
			add[p][v] = nil
		end
	end
	for p in pairs(multi) do
		for v in pairs(multi[p]) do
			multi[p][v] = nil
		end
	end
	for buff in pairs(InvenSimulatorCharDB.buffs) do
		if self.buffFrame.buff[buff] and self.buffFrame.buff[buff]:IsShown() then
			for p, v in pairs(self.buffFrame.buff[buff].addSpec) do
				add[buff] = add[buff] or {}
				add[buff][p] = v
			end
			for p, v in pairs(self.buffFrame.buff[buff].multiSpec) do
				multi[buff] = multi[buff] or {}
				multi[buff][p] = v
			end
		end
	end
	for stat, link in pairs(linkedBuff.add) do
		stat = stat:gsub("(%d+)", "")
		stat = stat == "초당 마나 회복량" and "5초당 마나 회복량" or stat
		maxValue = nil
		for idx, buff in ipairs(link) do
			if add[buff] and add[buff][stat] then
				if maxValue == nil then
					maxValue = add[buff][stat]
					maxIdx = idx
				elseif add[buff][stat] > maxValue then
					maxValue = add[buff][stat]
					maxIdx = idx
				end
			end
		end
		if maxValue then
			for idx, buff in pairs(link) do
				if idx ~= maxIdx and add[buff] and add[buff][stat] then
					add[buff][stat] = nil
				end
			end
		end
	end
	for stat, link in pairs(linkedBuff.multi) do
		stat = stat:gsub("(%d+)", "")
		stat = stat == "초당 마나 회복량" and "5초당 마나 회복량" or stat
		maxValue = nil
		for idx, buff in ipairs(link) do
			if multi[buff] and multi[buff][stat] then
				if maxValue == nil then
					maxValue = multi[buff][stat]
					maxIdx = idx
				elseif multi[buff][stat] > maxValue then
					maxValue = multi[buff][stat]
					maxIdx = idx
				end
			end
		end
		if maxValue then
			for idx, buff in pairs(link) do
				if idx ~= maxIdx and multi[buff] and multi[buff][stat] then
					multi[buff][stat] = nil
				end
			end
		end
	end
	self.buff_add = self.buff_add or {}
	self.buff_multi = self.buff_multi or {}
	self.buff_add["체력"] = 0
	self.buff_add["지능"] = 0
	self.buff_multi["체력"] = 1
	self.buff_multi["지능"] = 1
	for _, stats in pairs(add) do
		for p, v in pairs(stats) do
			if not isLastCalcSpec[p] then
				self:AddSpec(p, v)
			end
			if self.buff_add[p] then
				self.buff_add[p] = self.buff_add[p] + v
			end
		end
	end
	-- 특정 스텟 중 제일 높은 스텟 올리는 장신구 적용 (다크문 카드: 위대함 등)
	local stats, statName, statsTable, upvalue
	for i = 13, 14 do
		if self.buffFrame.buff[i] and self.buffFrame.buff[i]:IsShown() and self.db.buffs[i] and buffTooltipText[i] then
			stats, upvalue = buffTooltipText[i]:match("(.+) 중 가장 높은 능력치가 (%d+)만큼 증가")
			if stats and upvalue then
				stats = stats:trim()
				upvalue = tonumber(upvalue or 0) or 0
				if upvalue > 0 then
					statsTable = { (","):split(stats) }
					stats = nil
					for _, stat in ipairs(statsTable) do
						stat = stat:trim()
						if not stats or (self.specTable[stat] or 0) > stats then
							stats = self.specTable[stat] or 0
							statName = stat
						end
					end
					if stats and statName then
						self:AddSpec(statName, upvalue)
						--break
					end
				end
			end
		end
	end
	for _, stats in pairs(multi) do
		for p, v in pairs(stats) do
			if not isLastCalcSpec[p] and not isLastCalcSpecMulti[p] then
				self:MultiSpec(p, v)
			end
			if self.buff_multi[p] then
				self.buff_multi[p] = self.buff_multi[p] * (1 + v)
			end
		end
	end
end

function InvenSimulatorUI:ApplyLastBuff()
	for _, stats in pairs(add) do
		for p, v in pairs(stats) do
			if isLastCalcSpec[p] then
				self:AddSpec(p, v)
			end
		end
	end
	for _, stats in pairs(multi) do
		for p, v in pairs(stats) do
			if isLastCalcSpec[p] and not isLastCalcSpecMulti[p] then
				self:MultiSpec(p, v)
			end
		end
	end
	if self.class == "전사" and self.buffFrame.buff["방패 막기"] and self.buffFrame.buff["방패 막기"]:IsShown() and self.db.buffs["방패 막기"] then
		if self.db.talents["방어;방패 숙련"] then
			local bv = ceil(self.specTable["방패 피해 방어량"] or 0)
			self.specTable["방패 피해 방어량"] = bv + floor(bv / (1 + self.db.talents["방어;방패 숙련"] * 0.15))
		else
			self:MultiSpec("방패 피해 방어량", 1)
		end
	elseif self.class == "흑마법사" and self.db.buffs["생명력 전환의 문양"] and self.buffFrame.buff["생명력 전환의 문양"]:IsShown() then
		self:AddSpec("주문 공격력", self.specTable["정신력"] * 0.2)
		self:AddSpec("주문 치유량", self.specTable["정신력"] * 0.2)
	end
end

function InvenSimulatorUI:ApplyLastMultiBuff()
	for _, stats in pairs(multi) do
		for p, v in pairs(stats) do
			if isLastCalcSpecMulti[p] then
				self:MultiSpec(p, v)
			end
		end
	end
end