local _G = _G
local IRF3, noOption = ...
local pairs = _G.pairs
local ipairs = _G.ipairs
local unpack = _G.unpack
local select = _G.select
local twipe = _G.table.wipe
local tinsert = _G.table.insert
local UnitExists = _G.UnitExists
local UnitHealth = _G.UnitHealth
local UnitInRange = _G.UnitInRange
local UnitIsGhost = _G.UnitIsGhost
local UnitIsDead = _G.UnitIsDead
local UnitIsAFK = _G.UnitIsAFK
local UnitCanAttack = _G.UnitCanAttack
local UnitIsConnected = _G.UnitIsConnected
local UnitHasVehicleUI = _G.UnitHasVehicleUI
local UnitGroupRolesAssigned = _G.UnitGroupRolesAssigned
local UnitGetIncomingHeals = _G.UnitGetIncomingHeals
local UnitPowerType = _G.UnitPowerType
local UnitAlternatePowerInfo = _G.UnitAlternatePowerInfo
local GetRaidRosterInfo = _G.GetRaidRosterInfo
local InCombatLockdown = _G.InCombatLockdown
local SM = LibStub("LibSharedMedia-3.0")
local eventHandler = {}
IRF3 = _G[IRF3]
IRF3.visibleMembers = {}

function IRF3:SetupAll(update)
	for _, header in pairs(self.headers) do
		for _, member in pairs(header.members) do
			member:Setup()
		end
	end
	for _, member in pairs(self.petHeader.members) do
		member:Setup()
	end
end

local statusBarTexture = "Interface\\RaidFrame\\Raid-Bar-Resource-Fill"

local function setupMemberTexture(self)
	statusBarTexture = SM:Fetch("statusbar", IRF3.db.units.texture)
	self.powerBar:SetStatusBarTexture(statusBarTexture, "BORDER", -1)
	self.healthBar:SetStatusBarTexture(statusBarTexture, "BORDER", -1)
	self.myHealPredictionBar:SetStatusBarTexture(statusBarTexture, "BORDER", -1)
	self.myHealPredictionBar:SetStatusBarColor(IRF3.db.units.myHealPredictionColor[1], IRF3.db.units.myHealPredictionColor[2], IRF3.db.units.myHealPredictionColor[3], IRF3.db.units.healPredictionAlpha)
	self.otherHealPredictionBar:SetStatusBarTexture(statusBarTexture, "BORDER", -1)
	self.otherHealPredictionBar:SetStatusBarColor(IRF3.db.units.otherHealPredictionColor[1], IRF3.db.units.otherHealPredictionColor[2], IRF3.db.units.otherHealPredictionColor[3], IRF3.db.units.healPredictionAlpha)
	self.castingBar:SetStatusBarTexture(statusBarTexture, "BORDER", 0)
	self.castingBar:SetStatusBarColor(IRF3.db.units.castingBarColor[1], IRF3.db.units.castingBarColor[2], IRF3.db.units.castingBarColor[3])
	self.resurrectionBar:SetStatusBarTexture(statusBarTexture, "BORDER", 1)
	self.resurrectionBar:SetStatusBarColor(IRF3.db.units.resurrectionBarColor[1], IRF3.db.units.resurrectionBarColor[2], IRF3.db.units.resurrectionBarColor[3])
	self.bossDebuff:SetAlpha(IRF3.db.units.bossDebuffAlpha)
	if self.petButton then
		self.petButton.powerBar:SetStatusBarTexture(statusBarTexture, "BORDER", -1)
		self.petButton.healthBar:SetStatusBarTexture(statusBarTexture, "BORDER", -1)
		self.petButton.myHealPredictionBar:SetStatusBarTexture(statusBarTexture, "BORDER", -1)
		self.petButton.myHealPredictionBar:SetStatusBarColor(IRF3.db.units.myHealPredictionColor[1], IRF3.db.units.myHealPredictionColor[2], IRF3.db.units.myHealPredictionColor[3], IRF3.db.units.healPredictionAlpha)
		self.petButton.otherHealPredictionBar:SetStatusBarTexture(statusBarTexture, "BORDER", -1)
		self.petButton.otherHealPredictionBar:SetStatusBarColor(IRF3.db.units.otherHealPredictionColor[1], IRF3.db.units.otherHealPredictionColor[2], IRF3.db.units.otherHealPredictionColor[3], IRF3.db.units.healPredictionAlpha)
	end
end

local function setHorizontal(bar, parent)
	bar:SetOrientation("HORIZONTAL")
	bar:ClearAllPoints()
	bar:SetPoint("TOPLEFT", parent:GetStatusBarTexture(), "TOPRIGHT", 0, 0)
	bar:GetParent().orientation = 1
end

local function setVertical(bar, parent)
	bar:SetOrientation("VERTICAL")
	bar:ClearAllPoints()
	bar:SetPoint("BOTTOMLEFT", parent:GetStatusBarTexture(), "TOPLEFT", 0, 0)
	bar:GetParent().orientation = 2
end

local function setupMemberBarOrientation(self)
	if IRF3.db.units.orientation == 1 then
		self.healthBar:SetOrientation("HORIZONTAL")
		setHorizontal(self.myHealPredictionBar, self.healthBar)
		setHorizontal(self.otherHealPredictionBar, self.myHealPredictionBar)
	else
		self.healthBar:SetOrientation("VERTICAL")
		setVertical(self.myHealPredictionBar, self.healthBar)
		setVertical(self.otherHealPredictionBar, self.myHealPredictionBar)
	end
end

local function setupMemberPowerBar(self)
	self.healthBar:ClearAllPoints()
	self.powerBar:ClearAllPoints()
	if IRF3.db.units.powerBarPos == 1 or IRF3.db.units.powerBarPos == 2 then
		self.name:SetPoint("CENTER", self.healthBar, 0, 0)
		self.powerBar:SetWidth(0)
		self.powerBar:SetOrientation("HORIZONTAL")
		if IRF3.db.units.powerBarHeight > 0 then
			self.powerBar:SetHeight(IRF3.db.height * IRF3.db.units.powerBarHeight)
		else
			self.powerBar:SetHeight(0.001)
		end
		if IRF3.db.units.powerBarPos == 1 then
			self.healthBar:SetPoint("TOPLEFT", self.powerBar, "BOTTOMLEFT", 0, 0)
			self.healthBar:SetPoint("BOTTOMRIGHT", 0, 0)
			self.powerBar:SetPoint("TOPLEFT", 0, 0)
			self.powerBar:SetPoint("TOPRIGHT", 0, 0)
		else
			self.healthBar:SetPoint("TOPLEFT", 0, 0)
			self.healthBar:SetPoint("BOTTOMRIGHT", self.powerBar, "TOPRIGHT", 0, 0)
			self.powerBar:SetPoint("BOTTOMLEFT", 0, 0)
			self.powerBar:SetPoint("BOTTOMRIGHT", 0, 0)
		end
	else
		self.name:SetPoint("CENTER", 0, 0)
		self.powerBar:SetHeight(0)
		self.powerBar:SetOrientation("VERTICAL")
		if IRF3.db.units.powerBarHeight > 0 then
			self.powerBar:SetWidth(IRF3.db.width * IRF3.db.units.powerBarHeight)
		else
			self.powerBar:SetWidth(0.001)
		end
		if IRF3.db.units.powerBarPos == 3 then
			self.healthBar:SetPoint("TOPLEFT", self.powerBar, "TOPRIGHT", 0, 0)
			self.healthBar:SetPoint("BOTTOMRIGHT", 0, 0)
			self.powerBar:SetPoint("TOPLEFT", 0, 0)
			self.powerBar:SetPoint("BOTTOMLEFT", 0, 0)
		else
			self.healthBar:SetPoint("TOPLEFT", 0, 0)
			self.healthBar:SetPoint("BOTTOMRIGHT", self.powerBar, "BOTTOMLEFT", 0, 0)
			self.powerBar:SetPoint("TOPRIGHT", 0, 0)
			self.powerBar:SetPoint("BOTTOMRIGHT", 0, 0)
		end
	end
end

local function checkMouseOver(self)
	if not UnitIsUnit(self:GetParent().displayedUnit, "mouseover") then
		self:Hide()
	end
end

local function setupMemberOutline(self)
	self.outline:SetScript("OnUpdate", nil)
	self.outline:SetScale(self.optionTable.outline.scale)
	self.outline:SetAlpha(self.optionTable.outline.alpha)
	self:UnregisterEvent("PLAYER_TARGET_CHANGED")
	self:UnregisterEvent("UPDATE_MOUSEOVER_UNIT")
	if self.optionTable.outline.type == 2 then
		self:RegisterEvent("PLAYER_TARGET_CHANGED")
		self.outline:SetBackdropBorderColor(self.optionTable.outline.targetColor[1], self.optionTable.outline.targetColor[2], self.optionTable.outline.targetColor[3])
	elseif self.optionTable.outline.type == 3 then
		self:RegisterEvent("UPDATE_MOUSEOVER_UNIT")
		self.outline:SetBackdropBorderColor(self.optionTable.outline.mouseoverColor[1], self.optionTable.outline.mouseoverColor[2], self.optionTable.outline.mouseoverColor[3])
		self.outline:SetScript("OnUpdate", checkMouseOver)
	elseif self.optionTable.outline.type == 4 then
		self.outline:SetBackdropBorderColor(self.optionTable.outline.lowHealthColor[1], self.optionTable.outline.lowHealthColor[2], self.optionTable.outline.lowHealthColor[3])
	elseif self.optionTable.outline.type == 5 then
		self.outline:SetBackdropBorderColor(self.optionTable.outline.aggroColor[1], self.optionTable.outline.aggroColor[2], self.optionTable.outline.aggroColor[3])
	elseif self.optionTable.outline.type == 6 then
		self.outline:SetBackdropBorderColor(self.optionTable.outline.raidIconColor[1], self.optionTable.outline.raidIconColor[2], self.optionTable.outline.raidIconColor[3])
	else
		self.outline:Hide()
	end
	if self.petButton then
		setupMemberOutline(self.petButton)
	end
end

local function setupMemberDebuffIcon(self)
	if self.optionTable.debuffIconType == 1 then
		for i = 1, 5 do
			self["debuffIcon"..i].color:ClearAllPoints()
			self["debuffIcon"..i].color:SetAllPoints()
			self["debuffIcon"..i].color:Show()
			self["debuffIcon"..i].icon:ClearAllPoints()
			self["debuffIcon"..i].icon:SetPoint("TOPLEFT", 1, -1)
			self["debuffIcon"..i].icon:SetPoint("BOTTOMRIGHT", -1, 1)
			self["debuffIcon"..i].icon:Show()
		end
	elseif self.optionTable.debuffIconType == 2 then
		for i = 1, 5 do
			self["debuffIcon"..i].color:Hide()
			self["debuffIcon"..i].icon:ClearAllPoints()
			self["debuffIcon"..i].icon:SetPoint("TOPLEFT", 1, -1)
			self["debuffIcon"..i].icon:SetPoint("BOTTOMRIGHT", -1, 1)
			self["debuffIcon"..i].icon:Show()
		end
	else
		for i = 1, 5 do
			self["debuffIcon"..i].color:ClearAllPoints()
			self["debuffIcon"..i].color:SetPoint("TOPLEFT", 1, -1)
			self["debuffIcon"..i].color:SetPoint("BOTTOMRIGHT", -1, 1)
			self["debuffIcon"..i].color:Show()
			self["debuffIcon"..i].icon:Hide()
		end
	end
end

local function setupMemberAll(self)
	CompactUnitFrame_SetOptionTable(self, IRF3.db.units)
	self.background:SetTexture(IRF3.db.units.backgroundColor[1], IRF3.db.units.backgroundColor[2], IRF3.db.units.backgroundColor[3], IRF3.db.units.backgroundColor[4])
	if self.petButton then
		CompactUnitFrame_SetOptionTable(self.petButton, IRF3.db.units)
		self.petButton.background:SetTexture(IRF3.db.units.backgroundColor[1], IRF3.db.units.backgroundColor[2], IRF3.db.units.backgroundColor[3], IRF3.db.units.backgroundColor[4])
	end
	setupMemberTexture(self)
	setupMemberPowerBar(self)
	setupMemberBarOrientation(self)
	setupMemberOutline(self)
	setupMemberDebuffIcon(self)
	InvenRaidFrames3Member_SetupCastingBarPos(self)
	InvenRaidFrames3Member_SetupIconPos(self)
	self.name:SetFont(SM:Fetch("font", IRF3.db.font.file), IRF3.db.font.size, IRF3.db.font.attribute)
	self.name:SetShadowColor(0, 0, 0)
	if IRF3.db.font.shadow then
		self.name:SetShadowOffset(1, -1)
	else
		self.name:SetShadowOffset(0, 0)
	end
	InvenRaidFrames3Member_UpdateAll(self)
end

local function updateHealPredictionBarSize(self)
	self = self:GetParent()
	self.myHealPredictionBar:SetWidth(self.healthBar:GetWidth())
	self.myHealPredictionBar:SetHeight(self.healthBar:GetHeight())
	self.otherHealPredictionBar:SetWidth(self.healthBar:GetWidth())
	self.otherHealPredictionBar:SetHeight(self.healthBar:GetHeight())
end

function InvenRaidFrames3Base_OnLoad(self)
	self:RegisterForClicks("AnyUp")
	self:RegisterForDrag("LeftButton", "RightButton")
	self:RegisterEvent("UNIT_NAME_UPDATE")
	self:RegisterEvent("UNIT_CONNECTION")
	self:RegisterEvent("UNIT_HEALTH")
	self:RegisterEvent("UNIT_MAXHEALTH")
	self:RegisterEvent("UNIT_HEAL_PREDICTION")
	self:RegisterEvent("UNIT_POWER")
	self:RegisterEvent("UNIT_MAXPOWER")
	self:RegisterEvent("UNIT_DISPLAYPOWER")
	self:RegisterEvent("UNIT_POWER_BAR_SHOW")
	self:RegisterEvent("UNIT_POWER_BAR_HIDE")
	self:RegisterEvent("UNIT_FACTION")
	self:RegisterEvent("UNIT_AURA")
	self.timer, self.health, self.maxHealth, self.lostHealth = 0, 0, 1, 0
	CompactUnitFrame_SetOptionTable(self, noOption)
	self.healthBar:SetScript("OnSizeChanged", updateHealPredictionBarSize)
	if not self.petButton then
		setHorizontal(self.myHealPredictionBar, self.healthBar)
		setHorizontal(self.otherHealPredictionBar, self.myHealPredictionBar)
	end
	self:SetFrameStrata("MEDIUM")
	self:SetFrameLevel(self:GetParent():GetFrameLevel())
	RegisterUnitWatch(self)
end

local function isPetGroup(self)
	return self:GetParent() == IRF3.petHeader
end

function InvenRaidFrames3Member_OnLoad(self)
	InvenRaidFrames3Base_OnLoad(self)
	self.UpdateAll = InvenRaidFrames3Member_UpdateAll
	self.Setup = setupMemberAll
	self.SetupTexture = setupMemberTexture
	self.SetupPowerBar = setupMemberPowerBar
	self.SetupBarOrientation = setupMemberBarOrientation
	self.SetupCastingBarPos = InvenRaidFrames3Member_SetupCastingBarPos
	self.SetupIconPos = InvenRaidFrames3Member_SetupIconPos
	self.SetupOutline = setupMemberOutline
	self.SetupDebuffIcon = setupMemberDebuffIcon
	self:SetID(tonumber(self:GetName():match("UnitButton(%d+)$")))
	self:GetParent().members[self:GetID()] = self
	tinsert(UnitPopupFrames, self.dropDown:GetName())
	CompactUnitFrame_SetMenuFunc(self, CompactUnitFrameDropDown_Initialize)
	self.nameTable = {}
	self.name:SetDrawLayer("OVERLAY", 6)
	self.name:Show()
	self.readyCheckIcon:SetParent(self.topLevel)
	self.readyCheckIcon:SetDrawLayer("OVERLAY", 4)
	self.readyCheckIcon:ClearAllPoints()
	self.readyCheckIcon:SetPoint("CENTER", 0, 0)
	self.readyCheckIcon:SetSize(24, 24)
	self.roleIcon:SetTexture("Interface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES")
	self.roleIcon:SetSize(0.001, 0.001)
	self:RegisterEvent("PLAYER_ENTERING_WORLD")
	self:RegisterEvent("UNIT_THREAT_SITUATION_UPDATE")
	self:RegisterEvent("PLAYER_ROLES_ASSIGNED")
	self:RegisterEvent("RAID_TARGET_UPDATE")
	self:RegisterEvent("READY_CHECK_CONFIRM")
	self:RegisterEvent("UNIT_ENTERED_VEHICLE")
	self:RegisterEvent("UNIT_EXITED_VEHICLE")
	self:RegisterEvent("UNIT_PET")
	self:RegisterEvent("UNIT_SPELLCAST_START")
	self:RegisterEvent("UNIT_SPELLCAST_STOP")
	self:RegisterEvent("UNIT_SPELLCAST_DELAYED")
	self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START")
	self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE")
	self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP")
	if self:GetParent().index == 0 then
		if self:GetID() == 1 then
			self:RegisterEvent("PLAYER_FLAGS_CHANGED")
		else
			self:RegisterEvent("UNIT_FLAGS")
			self:RegisterEvent("PARTY_MEMBERS_CHANGED")
		end
	else
		self:RegisterEvent("UNIT_FLAGS")
		self:RegisterEvent("RAID_ROSTER_UPDATE")
	end
end

function InvenRaidFrames3Member_OnShow(self)
	if IRF3.db then
		self:SetScript("OnEvent", InvenRaidFrames3Member_OnEvent)
		self:SetScript("OnUpdate", InvenRaidFrames3Member_OnUpdate)
		self:GetParent().visible = self:GetParent().visible + 1
		InvenRaidFrames3Member_UpdateAll(self)
		if isPetGroup(self) then
			self:GetParent().border:SetAlpha(1)
		else
			IRF3:BorderUpdate()
		end
	end
	IRF3.visibleMembers[self] = true
end

function InvenRaidFrames3Member_OnHide(self)
	if IRF3.db then
		self:SetScript("OnEvent", nil)
		self:SetScript("OnUpdate", nil)
		self:GetParent().visible = self:GetParent().visible - 1
		InvenRaidFrames3Member_OnDragStop(self)
		if isPetGroup(self) then
			self:GetParent().border:SetAlpha(self:GetParent().visible > 0 and 1 or 0)
		else

			IRF3:BorderUpdate()
		end
		twipe(self.nameTable)
		self.lostHealth, self.hasAggro, self.isOffline, self.isAFK, self.color, self.class = 0
		self.unit, self.displayedUnit = nil
	end
	IRF3.visibleMembers[self] = nil
end

function InvenRaidFrames3Member_OnEnter(self)
	IRF3:SetHighlight(self)
end

function InvenRaidFrames3Member_OnLeave(self)
	IRF3:SetHighlight(nil)
end

function InvenRaidFrames3Member_OnDragStart(self)
	if not IRF3.db.lock then
		IRF3.dragging = self
		if isPetGroup(self) or self:GetParent() == InvenRaidFrames3PreviewPet then
			IRF3.petHeader:StartMoving()
		else
			IRF3:StartMoving()
		end
	end
end

function InvenRaidFrames3Member_OnDragStop(self)
	if IRF3.dragging then
		IRF3.dragging = nil
		if isPetGroup(self) or self:GetParent() == InvenRaidFrames3PreviewPet then
			IRF3.petHeader:SetUserPlaced(nil)
			IRF3.petHeader:StopMovingOrSizing()
		else
			IRF3:SetUserPlaced(nil)
			IRF3:StopMovingOrSizing()
		end
		IRF3:SavePosition()
	end
end

function InvenRaidFrames3Member_UpdateHealth(self)
	self.healthBar:SetValue(UnitHealth(self.displayedUnit))
	self.health = self.healthBar:GetValue()
	self.maxHealth = select(2, self.healthBar:GetMinMaxValues())
	self.lostHealth = self.maxHealth - self.health
end

local myIncomingHeal, allIncomingHeal

function InvenRaidFrames3Member_UpdateHealPrediction(self)
	if self.optionTable.displayHealPrediction then
		allIncomingHeal = UnitGetIncomingHeals(self.displayedUnit) or 0
		myIncomingHeal = UnitGetIncomingHeals(self.displayedUnit, "player") or 0
		if allIncomingHeal > 0 then
			if self.healIcon then
				if self.optionTable.healIcon and myIncomingHeal > 0 then
					self.healIcon:SetVertexColor(self.optionTable.myHealPredictionColor[1], self.optionTable.myHealPredictionColor[2], self.optionTable.myHealPredictionColor[3])
					self.healIcon:SetSize(self.optionTable.healIconSize, self.optionTable.healIconSize)
					self.healIcon:Show()
				elseif self.optionTable.healIconOther and (allIncomingHeal - myIncomingHeal) > 0 then
					self.healIcon:SetVertexColor(self.optionTable.otherHealPredictionColor[1], self.optionTable.otherHealPredictionColor[2], self.optionTable.otherHealPredictionColor[3])
					self.healIcon:SetSize(self.optionTable.healIconSize, self.optionTable.healIconSize)
					self.healIcon:Show()
				elseif self.healIcon:IsShown() then
					self.healIcon:SetSize(0.001, 0.001)
					self.healIcon:Hide()
				end
			end
			if self.lostHealth > 0 then
				if allIncomingHeal > self.lostHealth then
					allIncomingHeal = self.lostHealth
				end
				if allIncomingHeal < myIncomingHeal then
					myIncomingHeal, allIncomingHeal = allIncomingHeal, 0
				else
					allIncomingHeal = allIncomingHeal - myIncomingHeal
				end
				self.myHealPredictionBar:SetValue(myIncomingHeal)
				self.myHealPredictionBar:Show()
				self.otherHealPredictionBar:SetValue(allIncomingHeal)
				self.otherHealPredictionBar:Show()
			else
				self.myHealPredictionBar:Hide()
				self.otherHealPredictionBar:Hide()
			end
			return
		end
	end
	self.myHealPredictionBar:Hide()
	self.otherHealPredictionBar:Hide()
	if self.healIcon and self.healIcon:IsShown() then
		self.healIcon:SetSize(0.001, 0.001)
		self.healIcon:Hide()
	end
end

local colorR, colorG, colorB

function InvenRaidFrames3Member_UpdateState(self)
	self.class = select(2, UnitClass(self.displayedUnit))
	if UnitIsConnected(self.unit) then
		if UnitIsGhost(self.displayedUnit) then
			self.isGhost, self.isOffline, self.isDead, self.isAFK = true
		elseif UnitIsDead(self.displayedUnit) then
			self.isDead, self.isOffline, self.isGhost, self.isAFK = true
		elseif UnitIsAFK(self.unit) then
			self.isAFK, self.isOffline, self.isGhost, self.isDead = true
		else
			self.isGhost, self.isOffline, self.isDead, self.isAFK = nil
		end
		if self.isGhost or self.isDead then
			colorR, colorG, colorB = IRF3.db.colors.offline[1], IRF3.db.colors.offline[2], IRF3.db.colors.offline[3]
		elseif self.optionTable.useHarm and UnitCanAttack(self.displayedUnit, "player") then
			colorR, colorG, colorB = IRF3.db.colors.harm[1], IRF3.db.colors.harm[2], IRF3.db.colors.harm[3]
		elseif self.dispelType and IRF3.db.colors[self.dispelType] and self.optionTable.useDispelColor then
			colorR, colorG, colorB = IRF3.db.colors[self.dispelType][1], IRF3.db.colors[self.dispelType][2], IRF3.db.colors[self.dispelType][3]
		elseif self.displayedUnit:find("pet") then
			if self.petButton then
				colorR, colorG, colorB = IRF3.db.colors.vehicle[1], IRF3.db.colors.vehicle[2], IRF3.db.colors.vehicle[3]
			else
				colorR, colorG, colorB = IRF3.db.colors.pet[1], IRF3.db.colors.pet[2], IRF3.db.colors.pet[3]
			end
		elseif self.optionTable.useClassColors and IRF3.db.colors[self.class] then
			colorR, colorG, colorB = IRF3.db.colors[self.class][1], IRF3.db.colors[self.class][2], IRF3.db.colors[self.class][3]
		else
			colorR, colorG, colorB = IRF3.db.colors.help[1], IRF3.db.colors.help[2], IRF3.db.colors.help[3]
		end
	else
		self.isOffline, self.isGhost, self.isDead, self.isAFK = true
		colorR, colorG, colorB = IRF3.db.colors.offline[1], IRF3.db.colors.offline[2], IRF3.db.colors.offline[3]
	end
	self.healthBar:SetStatusBarColor(colorR, colorG, colorB)
	colorR, colorG, colorB = nil
end

local altR, altG, altB

function InvenRaidFrames3Member_UpdatePowerColor(self)
	if self.isOffline then
		colorR, colorG, colorB = IRF3.db.colors.offline[1], IRF3.db.colors.offline[2], IRF3.db.colors.offline[3]
	elseif select(7, UnitAlternatePowerInfo(self.displayedUnit)) then
		colorR, colorG, colorB = 0.7, 0.7, 0.6
	else
		colorR, colorG, altR, altG, altB = UnitPowerType(self.displayedUnit)
		if IRF3.db.colors[colorG] then
			colorR, colorG, colorB = IRF3.db.colors[colorG][1], IRF3.db.colors[colorG][2], IRF3.db.colors[colorG][3]
		elseif PowerBarColor[colorR] then
			colorR, colorG, colorB = PowerBarColor[colorR].r, PowerBarColor[colorR].g, PowerBarColor[colorR].b
		elseif altR then
			colorR, colorG, colorB = altR, altG, altB
		else
			colorR, colorG, colorB = PowerBarColor[0].r, PowerBarColor[0].g, PowerBarColor[0].b
		end
	end
	self.powerBar:SetStatusBarColor(colorR, colorG, colorB)
	colorR, colorG, colorB, altR, altG, altB = nil
end

local roleType

function InvenRaidFrames3Member_UpdateRoleIcon(self)
	if self.optionTable.displayRaidRoleIcon then
		roleType = UnitGroupRolesAssigned(self.unit)
		if roleType ~= "NONE" then
			self.roleIcon:SetTexCoord(GetTexCoordsForRoleSmallCircle(roleType))
			self.roleIcon:SetSize(self.optionTable.roleIconSize, self.optionTable.roleIconSize)
			return self.roleIcon:Show()
		end
	end
	self.roleIcon:SetSize(0.001, 0.001)
	self.roleIcon:Hide()
end

function InvenRaidFrames3Member_UpdateOutline(self)
	if self.optionTable.outline.type == 1 then	-- 해제 가능한 디버프
		if self.dispelType and IRF3.db.colors[self.dispelType] then
			self.outline:SetBackdropBorderColor(IRF3.db.colors[self.dispelType][1], IRF3.db.colors[self.dispelType][2], IRF3.db.colors[self.dispelType][3])
			return self.outline:Show()
		end
	elseif self.optionTable.outline.type == 2 then	-- 대상
		if UnitIsUnit(self.displayedUnit, "target") then
			return self.outline:Show()
		end
	elseif self.optionTable.outline.type == 3 then	-- 마우스 오버
		if UnitIsUnit(self.displayedUnit, "mouseover") then
			return self.outline:Show()
		end
	elseif self.optionTable.outline.type == 4 then	-- 체력 낮음
		if (self.health / self.maxHealth) <= self.optionTable.outline.lowHealth then
			return self.outline:Show()
		end
	elseif self.optionTable.outline.type == 5 then	-- 어그로
		if self.hasAggro then
			return self.outline:Show()
		end
	elseif self.optionTable.outline.type == 6 then	-- 전술목표 아이콘
		if self.optionTable.outline.raidIcon[GetRaidTargetIndex(self.displayedUnit)] then
			return self.outline:Show()
		end
	end
	self.outline:Hide()
end

local inRange, checkedRange, prevRange

function InvenRaidFrames3Member_OnUpdate(self, timer)
	self.timer = self.timer + timer
	if self.timer > 0.15 then
		self.timer = 0
		prevRange = self.outRange
		if self.isOffline then
			self.outRange = false
		else
			inRange, checkedRange = UnitInRange(self.displayedUnit)
			self.outRange = checkedRange and not inRange
		end
		if prevRange ~= self.outRange then
			if self.outRange then
				self.healthBar:SetAlpha(self.optionTable.fadeOutOfRangeHealth and self.optionTable.fadeOutAlpha or 1)
				self.powerBar:SetAlpha(self.optionTable.fadeOutOfRangePower and self.optionTable.fadeOutAlpha or 1)
			else
				self.healthBar:SetAlpha(1)
				self.powerBar:SetAlpha(1)
			end
			if self.petButton then
				InvenRaidFrames3Member_UpdateNameColor(self)
				InvenRaidFrames3Member_UpdateDisplayText(self)
				InvenRaidFrames3Member_OnUpdateSurvivalSkill(self)
				InvenRaidFrames3Member_UpdateRaidIconTarget(self)
			end
		elseif self.petButton then
			InvenRaidFrames3Member_OnUpdateSurvivalSkill(self)
			InvenRaidFrames3Member_UpdateRaidIconTarget(self)
		end
	end
end

function InvenRaidFrames3Member_OnUpdate2(self)
	if self.isOffline then
		self.outRange = false
	else
		inRange, checkedRange = UnitInRange(self.displayedUnit)
		self.outRange = checkedRange and not inRange
	end
	if self.outRange then
		self.healthBar:SetAlpha(self.optionTable.fadeOutOfRangeHealth and self.optionTable.fadeOutAlpha or 1)
		self.powerBar:SetAlpha(self.optionTable.fadeOutOfRangePower and self.optionTable.fadeOutAlpha or 1)
	else
		self.healthBar:SetAlpha(1)
		self.powerBar:SetAlpha(1)
	end
end

function InvenRaidFrames3Member_OnEvent(self, event, unit)
	eventHandler[event](self, unit)
end

function InvenRaidFrames3Member_UpdateAll(self)
	if IRF3.db then
		InvenRaidFrames3Member_UpdateInVehicle(self)
		if UnitExists(self.displayedUnit or "") then
			InvenRaidFrames3Member_UpdateName(self)
			InvenRaidFrames3Member_UpdateDebuffs(self)
			InvenRaidFrames3Member_UpdateState(self)
			InvenRaidFrames3Member_UpdateNameColor(self)
			CompactUnitFrame_UpdateMaxHealth(self)
			InvenRaidFrames3Member_UpdateHealth(self)
			InvenRaidFrames3Member_UpdateHealPrediction(self)
			CompactUnitFrame_UpdateMaxPower(self)
			CompactUnitFrame_UpdatePower(self)
			InvenRaidFrames3Member_UpdatePowerColor(self)
			InvenRaidFrames3Member_UpdateCastingBar(self)
			InvenRaidFrames3Member_UpdateThreat(self)
			InvenRaidFrames3Member_UpdateRoleIcon(self)
			InvenRaidFrames3Member_UpdateRaidIcon(self)
			InvenRaidFrames3Member_UpdateBuffs(self)
			InvenRaidFrames3Member_UpdateSpellTimer(self)
			InvenRaidFrames3Member_UpdateSurvivalSkill(self)
			InvenRaidFrames3Member_UpdateOutline(self)
			InvenRaidFrames3Member_UpdateResurrection(self)
			InvenRaidFrames3Member_OnUpdate2(self)
			InvenRaidFrames3Member_OnUpdateSurvivalSkill(self)
			InvenRaidFrames3Member_UpdateRaidIconTarget(self)
			InvenRaidFrames3Member_UpdateDisplayText(self)
		end
	end
end

function InvenRaidFrames3Member_UpdateInVehicle(self)
	self.unit = SecureButton_GetUnit(self)
	self.displayedUnit = self.unit and (SecureButton_GetModifiedUnit(self) or self.unit) or nil
	if self.petButton then
		if UnitExists(SecureButton_GetModifiedUnit(self.petButton) or "") then
			InvenRaidFrames3Pet_OnShow(self.petButton)
		else
			InvenRaidFrames3Pet_OnHide(self.petButton)
		end
	end
end

function InvenRaidFrames3Member_OnAttributeChanged(self, name, value)
	if name == "unit" then
		InvenRaidFrames3Member_UpdateAll(self)
	end
end

eventHandler.PLAYER_ENTERING_WORLD = InvenRaidFrames3Member_UpdateAll
eventHandler.PARTY_MEMBERS_CHANGED = InvenRaidFrames3Member_UpdateAll
eventHandler.RAID_ROSTER_UPDATE = InvenRaidFrames3Member_UpdateAll
eventHandler.PLAYER_ROLES_ASSIGNED = InvenRaidFrames3Member_UpdateRoleIcon
eventHandler.RAID_TARGET_UPDATE = function(self)
	InvenRaidFrames3Member_UpdateRaidIcon(self)
	if self.optionTable.outline.type == 6 then
		InvenRaidFrames3Member_UpdateOutline(self)
	end
end
eventHandler.UNIT_NAME_UPDATE = function(self, unit)
	if (unit == self.unit or unit == self.displayedUnit) then
		InvenRaidFrames3Member_UpdateName(self)
		InvenRaidFrames3Member_UpdateState(self)
		InvenRaidFrames3Member_UpdateNameColor(self)
		InvenRaidFrames3Member_UpdatePowerColor(self)
		InvenRaidFrames3Member_UpdateDisplayText(self)
		InvenRaidFrames3Member_UpdateResurrection(self)
		InvenRaidFrames3Member_UpdateBuffs(self)
	end
end
eventHandler.UNIT_CONNECTION = eventHandler.UNIT_NAME_UPDATE
eventHandler.UNIT_FLAGS = function(self, unit)
	if (unit == self.unit or unit == self.displayedUnit) then
		InvenRaidFrames3Member_UpdateState(self)
		InvenRaidFrames3Member_UpdateNameColor(self)
		InvenRaidFrames3Member_UpdateDisplayText(self)
		InvenRaidFrames3Member_UpdateResurrection(self)
		InvenRaidFrames3Member_UpdateBuffs(self)
	end
end
eventHandler.PLAYER_FLAGS_CHANGED = eventHandler.UNIT_FLAGS
eventHandler.UNIT_FACTION = eventHandler.UNIT_FLAGS
eventHandler.UNIT_MAXHEALTH = function(self, unit)
	if unit == self.displayedUnit then
		CompactUnitFrame_UpdateMaxHealth(self)
		InvenRaidFrames3Member_UpdateHealth(self)
		InvenRaidFrames3Member_UpdateDisplayText(self)
		InvenRaidFrames3Member_UpdateHealPrediction(self)
		if self.optionTable.outline.type == 4 then
			InvenRaidFrames3Member_UpdateOutline(self)
		end
	end
end
eventHandler.UNIT_HEALTH = function(self, unit)
	if unit == self.displayedUnit then
		InvenRaidFrames3Member_UpdateHealth(self)
		InvenRaidFrames3Member_UpdateState(self)
		InvenRaidFrames3Member_UpdateNameColor(self)
		InvenRaidFrames3Member_UpdateDisplayText(self)
		InvenRaidFrames3Member_UpdateHealPrediction(self)
		InvenRaidFrames3Member_UpdateResurrection(self)
		InvenRaidFrames3Member_UpdateBuffs(self)
		if self.optionTable.outline.type == 4 then
			InvenRaidFrames3Member_UpdateOutline(self)
		end
	end
end
eventHandler.UNIT_MAXPOWER = function(self, unit)
	if unit == self.displayedUnit then
		CompactUnitFrame_UpdateMaxPower(self)
		CompactUnitFrame_UpdatePower(self)
	end
end
eventHandler.UNIT_POWER = function(self, unit)
	if unit == self.displayedUnit then
		CompactUnitFrame_UpdatePower(self)
	end
end
eventHandler.UNIT_DISPLAYPOWER = function(self, unit)
	if unit == self.displayedUnit then
		CompactUnitFrame_UpdateMaxPower(self)
		CompactUnitFrame_UpdatePower(self)
		InvenRaidFrames3Member_UpdatePowerColor(self)
	end
end
eventHandler.UNIT_POWER_BAR_SHOW = eventHandler.UNIT_DISPLAYPOWER
eventHandler.UNIT_POWER_BAR_HIDE = eventHandler.UNIT_DISPLAYPOWER
eventHandler.UNIT_HEAL_PREDICTION = function(self, unit)
	if unit == self.displayedUnit then
		InvenRaidFrames3Member_UpdateHealPrediction(self)
	end
end
eventHandler.UNIT_AURA = function(self, unit)
	if (unit == self.unit or unit == self.displayedUnit) then
		InvenRaidFrames3Member_UpdateBuffs(self)
		InvenRaidFrames3Member_UpdateDebuffs(self)
		InvenRaidFrames3Member_UpdateSpellTimer(self)
		InvenRaidFrames3Member_UpdateSurvivalSkill(self)
		InvenRaidFrames3Member_UpdateDisplayText(self)
		if self.optionTable.outline.type == 1 then
			InvenRaidFrames3Member_UpdateOutline(self)
		end
		if self.optionTable.useDispelColor then
			InvenRaidFrames3Member_UpdateState(self)
		end
	end
end
eventHandler.UNIT_THREAT_SITUATION_UPDATE = function(self, unit)
	if unit == self.displayedUnit then
		InvenRaidFrames3Member_UpdateThreat(self)
		InvenRaidFrames3Member_UpdateDisplayText(self)
		if self.optionTable.outline.type == 5 then
			InvenRaidFrames3Member_UpdateOutline(self)
		end
	end
end
eventHandler.READY_CHECK_CONFIRM = function(self, unit)
	if unit == self.unit then
		InvenRaidFrames3Member_UpdateReadyCheck(self)
	end
end
eventHandler.UNIT_ENTERED_VEHICLE = function(self, unit)
	if unit == self.unit then
		InvenRaidFrames3Member_UpdateAll(self)
	end
end
eventHandler.UNIT_EXITED_VEHICLE = eventHandler.UNIT_ENTERED_VEHICLE
eventHandler.UNIT_PET = eventHandler.UNIT_ENTERED_VEHICLE
eventHandler.UNIT_SPELLCAST_START = function(self, unit)
	if unit == self.displayedUnit then
		InvenRaidFrames3Member_UpdateCastingBar(self)
	end
end
eventHandler.UNIT_SPELLCAST_STOP = eventHandler.UNIT_SPELLCAST_START
eventHandler.UNIT_SPELLCAST_DELAYED = eventHandler.UNIT_SPELLCAST_START
eventHandler.UNIT_SPELLCAST_CHANNEL_START = eventHandler.UNIT_SPELLCAST_START
eventHandler.UNIT_SPELLCAST_CHANNEL_UPDATE = eventHandler.UNIT_SPELLCAST_START
eventHandler.UNIT_SPELLCAST_CHANNEL_STOP = eventHandler.UNIT_SPELLCAST_START
eventHandler.PLAYER_TARGET_CHANGED = InvenRaidFrames3Member_UpdateOutline
eventHandler.UPDATE_MOUSEOVER_UNIT = InvenRaidFrames3Member_UpdateOutline