IRF_Buff = LibStub("AceAddon-3.0"):NewAddon("IRF_Buff", "AceEvent-3.0")
local self = IRF_Buff
local mother = InvenRaidFrames
local pos = { ["상단"] = "TOP", ["중앙"] = "CENTER", ["하단"] = "BOTTOM", ["좌측"] = "LEFT", ["좌측 상단"] = "TOPLEFT", ["좌측 하단"] = "BOTTOMLEFT", ["우측"] = "RIGHT", ["우측 상단"] = "TOPRIGHT", ["우측 하단"] = "BOTTOMRIGHT" }
self.vars = {
	frame = nil, unit = {}, paladin = UnitClass("player") == "성기사" and true or false,
	num = 0, buff = {}, cbuff = {}, bless = {}, icons = {}, combat = InCombatLockdown(), count = {}
}
local path = "Interface\\Icons\\"
local addminor = {
	["드루이드"] = { "야생의 징표" },
	["사제"] = { "신의 권능: 인내", "천상의 정신", "어둠의 보호" },
	["마법사"] = { "신비한 지능" },
}
local minorBuff = {
	["야생의 징표"] = "야생의 선물",
	["신의 권능: 인내"] = "인내의 기원",
	["천상의 정신"] = "정신력의 기원",
	["어둠의 보호"] = "암흑 보호의 기원",
	["신비한 지능"] = "신비한 총명함",
}
local UnitAura = _G.UnitAura
local tonumber = _G.tonumber
local pairs = _G.pairs
local unpack = _G.unpack
local f, am, id, b, fullname, buffed, name, icon, count, left, index, c, ins, itype, d, p, first, prev, n, set

function IRF_Buff:OnInitialize()
	if mother.vars.class == "흑마법사" or mother.vars.class == "주술사" then
		mother.db.char.checkbuff.spring = false
		mother.db.char.checkbuff.combat = true
	end
	f = CreateFrame("Frame", nil, UIParent)
	f:SetAlpha(mother.db.char.checkbuff.alpha)
	f:Show()
	self.vars.frame = f
	if self.vars.paladin then
		self.vars.num = 1
		self.vars.cbuff = { ["빛의 축복"] = 1, ["상급 빛의 축복"] = 1, ["왕의 축복"] = 1, ["상급 왕의 축복"] = 1, ["힘의 축복"] = 1, ["상급 힘의 축복"] = 1, ["지혜의 축복"] = 1, ["상급 지혜의 축복"] = 1, ["구원의 축복"] = 1, ["상급 구원의 축복"] = 1, ["성역의 축복"] = 1, ["상급 성역의 축복"] = 1 }
	else
		self.vars.num = #(mother.vars.buffcheck)
		for i = 1, self.vars.num do
			self.vars.cbuff[mother.vars.buffcheck[i]] = i
		end
		am = addminor[UnitClass("player")] or {}
		for i = 1, #(am) do
			self.vars.cbuff[am[i]] = i
		end
	end
	self:RegisterEvent("UNIT_AURA", function(event, unit) self:Update(unit) end)
	self:RegisterEvent("PLAYER_REGEN_ENABLED", function()
		self.vars.combat = false
		self:Update()
	end)
	self:RegisterEvent("PLAYER_REGEN_DISABLED", function()
		self.vars.combat = true
		self:Update()
	end)
	self:RegisterMessage("InvenRaidFrames_InitUnits", function() self:Update() end)
	self:RegisterMessage("InvenRaidFrames_UpdateScale", "SetScale")
	self:RegisterMessage("InvenRaidFrames_HideAll", function()
		for u in pairs(self.vars.unit) do
			for i = 1, self.vars.num do
				self.vars.unit[u][i]:SetTexture("")
				self.vars.unit[u][i]:Hide()
				self.vars.unit[u][i].count:SetText("")
			end
		end
	end)
	self:SetScale()
	self:SetLocation()
end

function IRF_Buff:ToggleBuff()
	if mother.db.char.checkbuff.togglemode then
		mother.db.char.checkbuff.toggle = not mother.db.char.checkbuff.toggle
		IRF_Buff:Update()
	end
end

function IRF_Buff:Update(unit)
	if unit then
		f = mother:GetUnit(unit)
		if f and mother.db.char.checkbuff.use and (not mother.db.char.checkbuff.togglemode) or (mother.db.char.checkbuff.togglemode and mother.db.char.checkbuff.toggle) then
			fullname = mother:GetUnitFullName(unit)
			if not fullname then return end
			b = self:Create(unit)
			if self.vars.paladin then
				self.vars.bless[fullname] = self.vars.bless[fullname] or { cast = "", buffed = false }
				buffed = false
				for spell, index in pairs(self.vars.cbuff) do
					name, _, icon, count, _, _, left = UnitAura(unit, spell, nil, "HELPFUL|PLAYER")
					if name then
						self.vars.bless[fullname].cast = icon
						buffed = true
						break
					end
				end
				self.vars.bless[fullname].buffed = buffed
			else
				self.vars.buff[unit] = { false, false, false, false }
				self.vars.count[unit] = { 0, 0, 0, 0 }
				for spell, index in pairs(self.vars.cbuff) do
					name, _, icon, count, _, _, left = UnitAura(unit, spell, nil, "HELPFUL")
					if name then
						if mother.vars.class == "주술사" and name == "물의 보호막" then
							if UnitIsUnit("player", unit) then
								self.vars.buff[unit][index] = true
								self.vars.count[unit][index] = count
							end
						else
							self.vars.buff[unit][index] = true
							self.vars.count[unit][index] = count
						end
					end
				end
			end
			self:DisplayBuff(unit)
		elseif self.vars.unit[unit] then
			self:ClearIcon(unit)
		end
	else
		for u in pairs(self.vars.unit) do
			if not mother.vars.unit[u] then
				for i = 1, self.vars.num do
					self.vars.unit[u][i]:SetTexture("")
					self.vars.unit[u][i]:Hide()
					self.vars.unit[u][i].count:SetText("")
				end
			end
		end
		for u in pairs(mother.vars.unit) do
			self:Update(u)
		end
	end
end

function IRF_Buff:ClearIcon(unit, id)
	if unit and self.vars.unit[unit] then
		if id then
			self.vars.unit[unit][id]:SetTexture("")
			self.vars.unit[unit][id]:Hide()
			self.vars.unit[unit][id].count:SetText("")
		else
			for i = 1, self.vars.num do
				self.vars.unit[unit][i]:SetTexture("")
				self.vars.unit[unit][i]:Hide()
				self.vars.unit[unit][i].count:SetText("")
			end
		end
	end
end

function IRF_Buff:ClearPet()
	for unit in pairs(self.vars.unit) do
		if strfind(unit, "pet") and not UnitExists(unit) then
			self:ClearIcon(unit)
		end
	end
end

function IRF_Buff:Create(unit)
	if not self.vars.unit[unit] then
		self.vars.unit[unit] = {}
		for i = 1, self.vars.num do
			self.vars.unit[unit][i] = self.vars.frame:CreateTexture(nil, "ARTWORK")
			self.vars.unit[unit][i]:SetTexture("")
			self.vars.unit[unit][i]:SetWidth(mother.db.char.checkbuff.size)
			self.vars.unit[unit][i]:SetHeight(mother.db.char.checkbuff.size)
			self.vars.unit[unit][i]:Hide()
			self.vars.unit[unit][i].count = self.vars.frame:CreateFontString(nil, "OVERLAY", "NumberFontNormalSmall")
			self.vars.unit[unit][i].count:SetPoint("CENTER", self.vars.unit[unit][i], "CENTER", 2, 0)
			self.vars.unit[unit][i].count:SetTextColor(1, 1, 1)
			self.vars.unit[unit][i].count:SetText("")
		end
	end
	return self.vars.unit[unit]
end

function IRF_Buff:Init(unit, icon, count, id)
	b = self.vars.unit[unit]
	if not b then return end
	if self.vars.combat and not mother.db.char.checkbuff.combat then
		self:ClearIcon(unit, id)
	else
		b[id]:SetTexture(icon)
		b[id]:Show()
		b[id].count:SetText((count and count > 1) and count or "")
	end
end

function IRF_Buff:GetBlessIcon(unit)
	c = UnitClass(unit)
	if c then
		name = InvenRaidFramesBuffCheckDB[c]
		if name then
			return GetSpellTexture("상급 "..name) or GetSpellTexture(name) or ""
		end
	end
	return nil
end

function IRF_Buff:DisplayBuff(unit)
	b = self.vars.unit[unit]
	if not b then return end
	if mother.db.char.checkbuff.togglemode then
		if not(UnitIsConnected(unit)) or UnitIsDeadOrGhost(unit) or not(mother.db.char.checkbuff.toggle) then
			self:ClearIcon(unit)
			return
		end
	else
		if not(UnitIsConnected(unit)) or UnitIsDeadOrGhost(unit) or (self.vars.combat and not mother.db.char.checkbuff.combat) or (not mother.db.char.checkbuff.pet and not UnitIsPlayer(unit)) then
			self:ClearIcon(unit)
			return
		end
		ins, itype = IsInInstance()
		if ins then
			if (((itype == "party" or itype == "raid") and not mother.db.char.checkbuff.zone2) or (itype == "arena" and not mother.db.char.checkbuff.zone3) or (itype == "pvp" and not mother.db.char.checkbuff.zone4)) then
				self:ClearIcon(unit)
				return
			end
		elseif not mother.db.char.checkbuff.zone1 then
			self:ClearIcon(unit)
			return
		end
	end
	if self.vars.paladin then
		fullname = mother:GetUnitFullName(unit)
		if fullname and self.vars.bless[fullname] then
			icon = self.vars.bless[fullname].cast
			buffed = self.vars.bless[fullname].buffed
			if icon == nil or icon == "" then
				icon = self:GetBlessIcon(unit)
			end
			if icon and mother.db.char.checkbuff.togglemode then
				if mother.db.char.checkbuff.toggle and buffed then
					self:Init(unit, icon, 1, 1)
					self:SetLocation(unit)
				else
					self:ClearIcon(unit, 1)
				end
			elseif icon and (mother.db.char.checkbuff.spring and not buffed) or (not mother.db.char.checkbuff.spring and buffed) then
				self:Init(unit, icon, 1, 1)
				self:SetLocation(unit)
			else
				self:ClearIcon(unit, 1)
			end
		else
			self:ClearIcon(unit, 1)
		end
	elseif self.vars.buff[unit] then
		--b = self.vars.buff[unit]
		set = false
		for i = 1, self.vars.num do
			name = mother.vars.buffcheck[i]
			local icon = (name == "영혼석 부활") and GetSpellTexture("영혼석 창조") or GetSpellTexture(name)
			local count = self.vars.count[unit][i]
			if icon and mother.db.char.checkbuff.togglemode then
				if mother.db.char.checkbuff.toggle and InvenRaidFramesBuffCheckDB[name] and b[i] then
					self:Init(unit, icon, count, i)
					set = true
				else
					self:ClearIcon(unit, i)
				end
			elseif icon and InvenRaidFramesBuffCheckDB[name] and ((mother.db.char.checkbuff.spring and not self.vars.buff[unit][i]) or (not mother.db.char.checkbuff.spring and self.vars.buff[unit][i])) then
				c = UnitClass(unit)
				if (c == "전사" or c == "도적") and (name == "신비한 지능" or name == "신비한 총명함") and mother.db.char.checkbuff.spring then
					self:ClearIcon(unit, i)
				else
					self:Init(unit, icon, count, i)
					set = true
				end
			else
				self:ClearIcon(unit, i)
			end
		end
		if set then
			self:SetLocation(unit)
		end
	else
		self:ClearIcon(unit)
	end

end

function IRF_Buff:SetLocation(unit)
	if unit then
		f = mother:GetUnit(unit)
		d = self.vars.unit[unit]
		if not (f and d) then
			self:ClearIcon(unit)
			return
		end
		self.vars.frame:SetFrameStrata(f:GetFrameStrata())
		self.vars.frame:SetFrameLevel(f.textparent:GetFrameLevel() + 3)
		p = mother.db.char.checkbuff.pos
		if self.vars.paladin then
			d[1]:ClearAllPoints()
			d[1]:SetPoint(pos[p], f, pos[p])
		else
			first, prev = true, nil
			if p == "중앙" or p == "상단" or p == "하단" then
				n = 0
				for i = 1, self.vars.num do
					if d[i]:IsVisible() then
						n = n + 1
					end
				end
				if n == 1 then
					for i = 1, self.vars.num do
						if d[i]:IsVisible() then
							d[i]:ClearAllPoints()
							d[i]:SetPoint(pos[p], f, pos[p])
							break
						end
					end
				elseif n == 2 then
					if d[1]:IsVisible() and d[2]:IsVisible() then
						d[1]:ClearAllPoints()
						d[2]:ClearAllPoints()
						d[1]:SetPoint((pos[p] == "CENTER" and "" or pos[p]).."RIGHT", f, pos[p])
						d[2]:SetPoint("LEFT", d[1], "RIGHT")
					elseif d[1]:IsVisible() and d[3]:IsVisible() then
						d[1]:ClearAllPoints()
						d[3]:ClearAllPoints()
						d[1]:SetPoint((pos[p] == "CENTER" and "" or pos[p]).."RIGHT", f, pos[p])
						d[3]:SetPoint("LEFT", d[1], "RIGHT")
					elseif d[2]:IsVisible() and d[3]:IsVisible() then
						d[2]:ClearAllPoints()
						d[3]:ClearAllPoints()
						d[2]:SetPoint((pos[p] == "CENTER" and "" or pos[p]).."RIGHT", f, pos[p])
						d[3]:SetPoint("LEFT", d[2], "RIGHT")
					end
				elseif n == 3 then
					d[1]:ClearAllPoints()
					d[2]:ClearAllPoints()
					d[3]:ClearAllPoints()
					d[2]:SetPoint(pos[p], f, pos[p])
					d[1]:SetPoint("RIGHT", d[2], "LEFT")
					d[3]:SetPoint("LEFT", d[2], "RIGHT")
				end
			elseif p == "좌측" or p == "좌측 상단" or p == "좌측 하단" then
				for i = 1, self.vars.num do
					if d[i]:IsVisible() then
						d[i]:ClearAllPoints()
						if first then
							first = false
							d[i]:SetPoint(pos[p], f, pos[p])
						else
							d[i]:SetPoint("LEFT", d[prev], "RIGHT")
						end
						prev = i
					end
				end
			elseif p == "우측" or p == "우측 상단" or p == "우측 하단" then
				for i = self.vars.num, 1, -1 do
					if d[i]:IsVisible() then
						d[i]:ClearAllPoints()
						if first then
							first = false
							d[i]:SetPoint(pos[p], f, pos[p])
						else
							d[i]:SetPoint("RIGHT", d[prev], "LEFT")
						end
						prev = i
					end
				end
			end
		end
	else
		for u in pairs(mother.vars.unit) do
			self:SetLocation(u)
		end
	end
end

function IRF_Buff:GetNumIcon(unit)
	if self.vars.unit[unit] then
		for i = 1, self.vars.num do
			if not self.vars.unit[unit][i]:IsVisible() then
				return i - 1
			end
		end
		return 4
	else
		return 0
	end
end

function IRF_Buff:SetSize(unit)
	if unit then
		if self.vars.unit[unit] then
			for i = 1, self.vars.num do
				self.vars.unit[unit][i]:SetWidth(mother.db.char.checkbuff.size)
				self.vars.unit[unit][i]:SetHeight(mother.db.char.checkbuff.size)
			end
		end
	else
		for u in pairs(mother.vars.unit) do
			self:SetSize(u)
		end
	end
end

function IRF_Buff:SetScale()
	self.vars.frame:SetScale(mother.db.profile.scale)
end