--[[
# Element: Health Bar

Handles the updating of a status bar that displays the unit's health.

## Widget

Health - A `StatusBar` used to represent the unit's health.

## Sub-Widgets

.TempLoss                  - A `StatusBar` used to represent temporary max health reduction.
.HealingAll                - A `StatusBar` used to represent incoming heals from all sources.
.HealingPlayer             - A `StatusBar` used to represent incoming heals from the player.
.HealingOther              - A `StatusBar` used to represent incoming heals from others.
.OverHealIndicator         - A `Texture` used to indicate that the incoming healing is greater than the configured limits.
.DamageAbsorb              - A `StatusBar` used to represent damage absorbs.
.OverDamageAbsorbIndicator - A `Texture` used to signify that the amount of damage absorb is greater than the configured limits.
.HealAbsorb                - A `StatusBar` used to represent heal absorbs.
.OverHealAbsorbIndicator   - A `Texture` used to signify that the amount of heal absorb is greater than the configured limits.

## Notes

A default texture will be applied if the widget is a StatusBar and doesn't have a texture set.
A default texture will be applied to the Texture widgets if they don't have a texture or a color set.

## Options

.considerSelectionInCombatHostile - Indicates whether selection should be considered hostile while the unit is in
                                    combat with the player (boolean)
.smoothing                        - Which status bar smoothing method to use, defaults to
                                    `Enum.StatusBarInterpolation.Immediate` (number)
.maximumHealthClampMode           - Defines how maximum health should clamp. See [Enum.UnitMaximumHealthMode](https://warcraft.wiki.gg/wiki/Enum.UnitMaximumHealthMode).
.damageAbsorbClampMode            - Defines how damage absorbs should clamp. See [Enum.UnitDamageAbsorbClampMode](https://warcraft.wiki.gg/wiki/Enum.UnitDamageAbsorbClampMode).
.healAbsorbClampMode              - Defines how healing absorbs should clamp. See [Enum.UnitHealAbsorbClampMode](https://warcraft.wiki.gg/wiki/Enum.UnitHealAbsorbClampMode).
.healAbsorbMode                   - Defines how healing absorbs should be treated. See [Enum.UnitHealAbsorbMode](https://warcraft.wiki.gg/wiki/Enum.UnitHealAbsorbMode).
.incomingHealClampMode            - Defines how incoming healing should clamp. See [Enum.UnitIncomingHealClampMode](https://warcraft.wiki.gg/wiki/Enum.UnitIncomingHealClampMode).
.incomingHealOverflow             - The maximum amount of overflow past the end of the health bar. Set this to 1 to disable the overflow.
                                    Defaults to 1.05 (number)

The following options are listed by priority. The first check that returns true decides the color of the health bar.

.colorDisconnected - Use `self.colors.disconnected` to color the bar if the unit is offline (boolean)
.colorTapping      - Use `self.colors.tapping` to color the bar if the unit isn't tapped by the player (boolean)
.colorThreat       - Use `self.colors.threat[threat]` to color the bar based on the unit's threat status. `threat` is
                     defined by the first return of [UnitThreatSituation](https://warcraft.wiki.gg/wiki/API_UnitThreatSituation) (boolean)
.colorClass        - Use `self.colors.class[class]` to color the bar based on unit class. `class` is defined by the
                     second return of [UnitClass](https://warcraft.wiki.gg/wiki/API_UnitClass) (boolean)
.colorClassNPC     - Use `self.colors.class[class]` to color the bar if the unit is a NPC (boolean)
.colorClassPet     - Use `self.colors.class[class]` to color the bar if the unit is player controlled, but not a player
                     (boolean)
.colorSelection    - Use `self.colors.selection[selection]` to color the bar based on the unit's outline/highlight
                     color. `selection` is defined by the return value of Private.unitSelectionType, a wrapper function
                     for [UnitSelectionType](https://warcraft.wiki.gg/wiki/API_UnitSelectionType) (boolean)
.colorReaction     - Use `self.colors.reaction[reaction]` to color the bar based on the player's reaction towards the
                     unit. `reaction` is defined by the return value of
                     [UnitReaction](https://warcraft.wiki.gg/wiki/API_UnitReaction) (boolean)
.colorSmooth       - Use color curve from `self.colors.health` to color the bar with a smooth gradient based on the
                     unit's current health percentage (boolean)
.colorHealth       - Use `self.colors.health` to color the bar. This flag is used to reset the bar color back to default
                     if none of the above conditions are met (boolean)

## Attributes

.values - A [unit health prediction calculator](https://warcraft.wiki.gg/wiki/API_CreateUnitHealPredictionCalculator) used to calculate the values used in this element.

## Examples

    -- Position and size
    local Health = CreateFrame('StatusBar', nil, self)
    Health:SetHeight(20)
    Health:SetPoint('TOP')
    Health:SetPoint('LEFT')
    Health:SetPoint('RIGHT')

    -- Options
    Health.colorTapping = true
    Health.colorDisconnected = true
    Health.colorClass = true
    Health.colorReaction = true
    Health.colorHealth = true

    -- Register it with oUF
    self.Health = Health

    -- Alternatively, if .TempLoss is being used
    local TempLoss = CreateFrame('StatusBar', nil, self)
    TempLoss:SetStatusBarTexture('UI-HUD-UnitFrame-Target-PortraitOn-Bar-TempHPLoss')
    TempLoss:SetReverseFill(true)
    TempLoss:SetHeight(20)
    TempLoss:SetPoint('TOP')
    TempLoss:SetPoint('LEFT')
    TempLoss:SetPoint('RIGHT')

    local Health = CreateFrame('StatusBar', nil, self)
    Health:SetPoint('LEFT')
    Health:SetPoint('TOPRIGHT', TempLoss:GetStatusBarTexture(), 'TOPLEFT')
    Health:SetPoint('BOTTOMRIGHT', TempLoss:GetStatusBarTexture(), 'BOTTOMLEFT')

	-- Optionally with healing prediction and absorbtion sub-widgets
    local HealingAll = CreateFrame('StatusBar', nil, self.Health)
    HealingAll:SetPoint('TOP')
    HealingAll:SetPoint('BOTTOM')
    HealingAll:SetPoint('LEFT', self.Health:GetStatusBarTexture(), 'RIGHT')
    HealingAll:SetWidth(200)
    HealingAll:SetStatusBarTexture('Interface\\TargetingFrame\\UI-StatusBar')
    self.Health.HealingAll = HealingAll

    local DamageAbsorb = CreateFrame('StatusBar', nil, self.Health)
    DamageAbsorb:SetPoint('TOP')
    DamageAbsorb:SetPoint('BOTTOM')
    DamageAbsorb:SetPoint('LEFT', HealingAll:GetStatusBarTexture(), 'RIGHT')
    DamageAbsorb:SetWidth(200)
    self.Health.DamageAbsorb = DamageAbsorb

    local HealAbsorb = CreateFrame('StatusBar', nil, self.Health)
    HealAbsorb:SetPoint('TOP')
    HealAbsorb:SetPoint('BOTTOM')
    HealAbsorb:SetPoint('RIGHT', self.Health:GetStatusBarTexture())
    HealAbsorb:SetWidth(200)
    HealAbsorb:SetReverseFill(true)
    self.Health.HealAbsorb = HealAbsorb

    local OverDamageAbsorbIndicator = self.Health:CreateTexture(nil, "OVERLAY")
    OverDamageAbsorbIndicator:SetPoint('TOP')
    OverDamageAbsorbIndicator:SetPoint('BOTTOM')
    OverDamageAbsorbIndicator:SetPoint('LEFT', self.Health, 'RIGHT')
    OverDamageAbsorbIndicator:SetWidth(10)
    self.Health.OverDamageAbsorbIndicator = OverDamageAbsorbIndicator

    local OverHealAbsorbIndicator = self.Health:CreateTexture(nil, "OVERLAY")
    OverHealAbsorbIndicator:SetPoint('TOP')
    OverHealAbsorbIndicator:SetPoint('BOTTOM')
    OverHealAbsorbIndicator:SetPoint('RIGHT', self.Health, 'LEFT')
    OverHealAbsorbIndicator:SetWidth(10)
    self.Health.OverHealAbsorbIndicator = OverHealAbsorbIndicator

    -- Options
    Health.colorTapping = true
    Health.colorDisconnected = true
    Health.colorClass = true
    Health.colorReaction = true
    Health.colorHealth = true

    -- Register it with oUF
    Health.TempLoss = TempLoss
    self.Health = Health
--]]

local _, ns = ...
local oUF = ns.oUF
local Private = oUF.Private

local unitSelectionType = Private.unitSelectionType

local function GetAccessibleColor(colors, key)
	if(canaccessvalue and not canaccessvalue(key)) then return end
	if(issecretvalue and issecretvalue(key)) then return end
	if(key == nil) then return end
	return colors[key]
end

local function UpdateColor(self, event, unit)
	if(not unit or self.unit ~= unit) then return end
	local element = self.Health

	local color
	if(element.colorDisconnected and not UnitIsConnected(unit)) then
		color = self.colors.disconnected
	elseif(element.colorTapping and not UnitPlayerControlled(unit) and UnitIsTapDenied(unit)) then
		color = self.colors.tapped
	elseif(element.colorThreat and not UnitPlayerControlled(unit) and UnitThreatSituation('player', unit)) then
		color = GetAccessibleColor(self.colors.threat, UnitThreatSituation('player', unit))
	elseif(element.colorClass and (UnitIsPlayer(unit) or UnitInPartyIsAI(unit)))
		or (element.colorClassNPC and not (UnitIsPlayer(unit) or UnitInPartyIsAI(unit)))
		or (element.colorClassPet and UnitPlayerControlled(unit) and not UnitIsPlayer(unit)) then
		local _, class = UnitClass(unit)
		color = GetAccessibleColor(self.colors.class, class)
	elseif(element.colorSelection and unitSelectionType(unit, element.considerSelectionInCombatHostile)) then
		color = GetAccessibleColor(self.colors.selection, unitSelectionType(unit, element.considerSelectionInCombatHostile))
	elseif(element.colorReaction and UnitReaction(unit, 'player')) then
		color = GetAccessibleColor(self.colors.reaction, UnitReaction(unit, 'player'))
	elseif(element.colorSmooth and self.colors.health:GetCurve()) then
		color = element.values:EvaluateCurrentHealthPercent(self.colors.health:GetCurve())
	elseif(element.colorHealth) then
		color = self.colors.health
	end

	color = color or self.colors.health
	if(color) then
		element:SetStatusBarColor(color:GetRGB())
	end

	--[[ Callback: Health:PostUpdateColor(unit, color)
	Called after the element color has been updated.

	* self  - the Health element
	* unit  - the unit for which the update has been triggered (string)
	* color - the used ColorMixin-based object (table?)
	--]]
	if(element.PostUpdateColor) then
		element:PostUpdateColor(unit, color)
	end
end

local function ColorPath(self, ...)
	--[[ Override: Health.UpdateColor(self, event, unit)
	Used to completely override the internal function for updating the widgets' colors.

	* self  - the parent object
	* event - the event triggering the update (string)
	* unit  - the unit accompanying the event (string)
	--]]
	(self.Health.UpdateColor or UpdateColor) (self, ...)
end

local function Update(self, event, unit)
	if(not unit or self.unit ~= unit) then return end
	local element = self.Health

	--[[ Callback: Health:PreUpdate(unit)
	Called before the element has been updated.

	* self - the Health element
	* unit - the unit for which the update has been triggered (string)
	--]]
	if(element.PreUpdate) then
		element:PreUpdate(unit)
	end

	UnitGetDetailedHealPrediction(unit, 'player', element.values)

	local max = element.values:GetMaximumHealth()
	element:SetMinMaxValues(0, max)

	local cur = element.values:GetCurrentHealth()
	if(UnitIsConnected(unit)) then
		element:SetValue(cur, element.smoothing)
	else
		element:SetValue(max, element.smoothing)
	end

	element.cur = cur -- DEPRECATED: use element.values
	element.max = max -- DEPRECATED: use element.values

	if(element.HealingAll or element.HealingPlayer or element.HealingOther or element.OverHealIndicator) then
		local allHeal, playerHeal, otherHeal, healClamped = element.values:GetIncomingHeals()
		if(element.HealingAll) then
			element.HealingAll:SetMinMaxValues(0, max)
			element.HealingAll:SetValue(allHeal)
		end
		if(element.HealingPlayer) then
			element.HealingPlayer:SetMinMaxValues(0, max)
			element.HealingPlayer:SetValue(playerHeal)
		end
		if(element.HealingOther) then
			element.HealingOther:SetMinMaxValues(0, max)
			element.HealingOther:SetValue(otherHeal)
		end
		if(element.OverHealIndicator) then
			element.OverHealIndicator:SetAlphaFromBoolean(healClamped, 1, 0)
		end
	end

	if(element.DamageAbsorb or element.OverDamageAbsorbIndicator) then
		local damageAbsorbAmount, damageAbsorbClamped = element.values:GetDamageAbsorbs()
		if(element.DamageAbsorb) then
			element.DamageAbsorb:SetMinMaxValues(0, max)
			element.DamageAbsorb:SetValue(damageAbsorbAmount)
		end
		if(element.OverDamageAbsorbIndicator) then
			element.OverDamageAbsorbIndicator:SetAlphaFromBoolean(damageAbsorbClamped, 1, 0)
		end
	end

	if(element.HealAbsorb or element.OverHealAbsorbIndicator) then
		local healAbsorbAmount, healAbsorbClamped = element.values:GetHealAbsorbs()
		if(element.HealAbsorb) then
			element.HealAbsorb:SetMinMaxValues(0, max)
			element.HealAbsorb:SetValue(healAbsorbAmount)
		end
		if(element.OverHealAbsorbIndicator) then
			element.OverHealAbsorbIndicator:SetAlphaFromBoolean(healAbsorbClamped, 1, 0)
		end
	end

	local lossPerc = 0
	if(element.TempLoss) then
		lossPerc = GetUnitTotalModifiedMaxHealthPercent(unit)
		element.TempLoss:SetValue(lossPerc, element.smoothing)
	end

	--[[ Callback: Health:PostUpdate(unit, cur, max, lossPerc)
	Called after the element has been updated.

	* self     - the Health element
	* unit     - the unit for which the update has been triggered (string)
	* cur      - the unit's current health value (number)
	* max      - the unit's maximum possible health value (number)
	* lossPerc - the percent by which the unit's max health has been temporarily reduced (number)
	--]]
	if(element.PostUpdate) then
		element:PostUpdate(unit, cur, max, lossPerc)
	end
end

local function UpdatePredictionSize(self, event, unit)
	local element = self.Health

	if(element.HealingAll) then
		element.HealingAll[element.__isHoriz and 'SetWidth' or 'SetHeight'](element.HealingAll, element.__size)
	end

	if(element.HealingPlayer) then
		element.HealingPlayer[element.__isHoriz and 'SetWidth' or 'SetHeight'](element.HealingPlayer, element.__size)
	end

	if(element.HealingOther) then
		element.HealingOther[element.__isHoriz and 'SetWidth' or 'SetHeight'](element.HealingOther, element.__size)
	end

	if(element.DamageAbsorb) then
		element.DamageAbsorb[element.__isHoriz and 'SetWidth' or 'SetHeight'](element.DamageAbsorb, element.__size)
	end

	if(element.HealAbsorb) then
		element.HealAbsorb[element.__isHoriz and 'SetWidth' or 'SetHeight'](element.HealAbsorb, element.__size)
	end
end

local function shouldUpdatePredictionSize(self)
	local element = self.Health

	local isHoriz = element:GetOrientation() == 'HORIZONTAL'
	local newSize = element[isHoriz and 'GetWidth' or 'GetHeight'](element)
	if(isHoriz ~= element.__isHoriz or newSize ~= element.__size) then
		element.__isHoriz = isHoriz
		element.__size = newSize

		return true
	end
end

local function Path(self, ...)
	--[[ Override: Health.UpdatePredictionSize(self, event, unit, ...)
	Used to completely override the internal function for updating the healing prediction sub-widgets' size.

	* self  - the parent object
	* event - the event triggering the update (string)
	* unit  - the unit accompanying the event (string)
	* ...   - the arguments accompanying the event
	--]]
	if(shouldUpdatePredictionSize(self)) then
		(self.Health.UpdatePredictionSize or UpdatePredictionSize) (self, ...)
	end

	--[[ Override: Health.Override(self, event, unit)
	Used to completely override the internal update function.

	* self  - the parent object
	* event - the event triggering the update (string)
	* unit  - the unit accompanying the event (string)
	--]]
	do
		(self.Health.Override or Update) (self, ...)
	end

	ColorPath(self, ...)
end

local function ForceUpdate(element)
	element.__isHoriz = nil
	element.__size = nil

	Path(element.__owner, 'ForceUpdate', element.__owner.unit)
end

--[[ Health:SetColorDisconnected(state, isForced)
Used to toggle coloring if the unit is offline.

* self     - the Health element
* state    - the desired state (boolean)
* isForced - forces the event update even if the state wasn't changed (boolean)
--]]
local function SetColorDisconnected(element, state, isForced) -- DEPRECATED
	if(element.colorDisconnected ~= state or isForced) then
		element.colorDisconnected = state
	end
end

--[[ Health:SetColorSelection(state, isForced)
Used to toggle coloring by the unit's selection.

* self     - the Health element
* state    - the desired state (boolean)
* isForced - forces the event update even if the state wasn't changed (boolean)
--]]
local function SetColorSelection(element, state, isForced)
	if(element.colorSelection ~= state or isForced) then
		element.colorSelection = state
		if(state) then
			element.__owner:RegisterEvent('UNIT_FLAGS', ColorPath)
		else
			element.__owner:UnregisterEvent('UNIT_FLAGS', ColorPath)
		end
	end
end

--[[ Health:SetColorTapping(state, isForced)
Used to toggle coloring if the unit isn't tapped by the player.

* self     - the Health element
* state    - the desired state (boolean)
* isForced - forces the event update even if the state wasn't changed (boolean)
--]]
local function SetColorTapping(element, state, isForced)
	if(element.colorTapping ~= state or isForced) then
		element.colorTapping = state
		if(state) then
			element.__owner:RegisterEvent('UNIT_FACTION', ColorPath)
		elseif(not element.colorReaction) then
			element.__owner:UnregisterEvent('UNIT_FACTION', ColorPath)
		end
	end
end

--[[ Health:SetColorReaction(state, isForced)
Used to toggle coloring by the unit's reaction.

* self     - the Health element
* state    - the desired state (boolean)
* isForced - forces the event update even if the state wasn't changed (boolean)
--]]
local function SetColorReaction(element, state, isForced)
	if(element.colorReaction ~= state or isForced) then
		element.colorReaction = state
		if(state) then
			element.__owner:RegisterEvent('UNIT_FACTION', ColorPath)
		elseif(not element.colorTapping) then
			element.__owner:UnregisterEvent('UNIT_FACTION', ColorPath)
		end
	end
end

--[[ Health:SetColorThreat(state, isForced)
Used to toggle coloring by the unit's threat status.

* self     - the Health element
* state    - the desired state (boolean)
* isForced - forces the event update even if the state wasn't changed (boolean)
--]]
local function SetColorThreat(element, state, isForced)
	if(element.colorThreat ~= state or isForced) then
		element.colorThreat = state
		if(state) then
			element.__owner:RegisterEvent('UNIT_THREAT_LIST_UPDATE', ColorPath)
		else
			element.__owner:UnregisterEvent('UNIT_THREAT_LIST_UPDATE', ColorPath)
		end
	end
end

local function Enable(self, unit)
	local element = self.Health
	if(element) then
		element.__owner = self
		element.ForceUpdate = ForceUpdate
		element.SetColorDisconnected = SetColorDisconnected
		element.SetColorSelection = SetColorSelection
		element.SetColorTapping = SetColorTapping
		element.SetColorReaction = SetColorReaction
		element.SetColorThreat = SetColorThreat

		if(element.values) then
			element.values:ResetPredictedValues()
		else
			element.values = CreateUnitHealPredictionCalculator()
		end

		if(not element.smoothing) then
			element.smoothing = Enum.StatusBarInterpolation.Immediate
		end

		if(element.maximumHealthClampMode) then
			element.values:SetMaximumHealthMode(element.maximumHealthClampMode)
		end

		if(element.damageAbsorbClampMode) then
			element.values:SetDamageAbsorbClampMode(element.damageAbsorbClampMode)
		end

		if(element.healAbsorbClampMode) then
			element.values:SetHealAbsorbClampMode(element.healAbsorbClampMode)
		end

		if(element.healAbsorbMode) then
			element.values:SetHealAbsorbMode(element.healAbsorbMode)
		end

		if(element.incomingHealClampMode) then
			element.values:SetIncomingHealClampMode(element.incomingHealClampMode)
		end

		if(element.incomingHealOverflow) then
			element.values:SetIncomingHealOverflowPercent(element.incomingHealOverflow)
		end

		self:RegisterEvent('UNIT_HEALTH', Path)
		self:RegisterEvent('UNIT_MAXHEALTH', Path)
		self:RegisterEvent('UNIT_CONNECTION', Path)

		if(unit == 'party' or unit == 'raid') then
			self:RegisterEvent('PARTY_MEMBER_ENABLE', Path)
			self:RegisterEvent('PARTY_MEMBER_DISABLE', Path)
		end

		if(element.colorSelection) then
			self:RegisterEvent('UNIT_FLAGS', ColorPath)
		end

		if(element.colorTapping or element.colorReaction) then
			self:RegisterEvent('UNIT_FACTION', ColorPath)
		end

		if(element.colorThreat) then
			self:RegisterEvent('UNIT_THREAT_LIST_UPDATE', ColorPath)
		end

		if(element.HealingAll or element.HealingPlayer or element.HealingOther or element.OverHealIndicator) then
			self:RegisterEvent('UNIT_HEAL_PREDICTION', Path)
		end

		if(element.DamageAbsorb or element.OverDamageAbsorbIndicator) then
			self:RegisterEvent('UNIT_ABSORB_AMOUNT_CHANGED', Path)
		end

		if(element.HealAbsorb or element.OverHealAbsorbIndicator) then
			self:RegisterEvent('UNIT_HEAL_ABSORB_AMOUNT_CHANGED', Path)
		end

		if(element.TempLoss) then
			self:RegisterEvent('UNIT_MAX_HEALTH_MODIFIERS_CHANGED', Path)
		end

		if(element:IsObjectType('StatusBar') and not element:GetStatusBarTexture()) then
			element:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
		end

		if(element.HealingAll) then
			if(element.HealingAll:IsObjectType('StatusBar') and not element.HealingAll:GetStatusBarTexture()) then
				element.HealingAll:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
			end
		end

		if(element.HealingPlayer) then
			if(element.HealingPlayer:IsObjectType('StatusBar') and not element.HealingPlayer:GetStatusBarTexture()) then
				element.HealingPlayer:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
			end
		end

		if(element.HealingOther) then
			if(element.HealingOther:IsObjectType('StatusBar') and not element.HealingOther:GetStatusBarTexture()) then
				element.HealingOther:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
			end
		end

		if(element.OverHealIndicator) then
			if(element.OverHealIndicator:IsObjectType('Texture') and not element.OverHealIndicator:GetTexture()) then
				element.OverHealIndicator:SetTexture([[Interface\RaidFrame\Shield-Overshield]])
				element.OverHealIndicator:SetBlendMode('ADD')
			end
		end

		if(element.DamageAbsorb) then
			if(element.DamageAbsorb:IsObjectType('StatusBar') and not element.DamageAbsorb:GetStatusBarTexture()) then
				element.DamageAbsorb:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
			end
		end

		if(element.HealAbsorb) then
			if(element.HealAbsorb:IsObjectType('StatusBar') and not element.HealAbsorb:GetStatusBarTexture()) then
				element.HealAbsorb:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
			end
		end

		if(element.OverDamageAbsorbIndicator) then
			if(element.OverDamageAbsorbIndicator:IsObjectType('Texture') and not element.OverDamageAbsorbIndicator:GetTexture()) then
				element.OverDamageAbsorbIndicator:SetTexture([[Interface\RaidFrame\Shield-Overshield]])
				element.OverDamageAbsorbIndicator:SetBlendMode('ADD')
			end
		end

		if(element.OverHealAbsorbIndicator) then
			if(element.OverHealAbsorbIndicator:IsObjectType('Texture') and not element.OverHealAbsorbIndicator:GetTexture()) then
				element.OverHealAbsorbIndicator:SetTexture([[Interface\RaidFrame\Absorb-Overabsorb]])
				element.OverHealAbsorbIndicator:SetBlendMode('ADD')
			end
		end

		element:Show()

		if(element.TempLoss) then
			if(element.TempLoss:IsObjectType('StatusBar')) then
				element.TempLoss:SetMinMaxValues(0, 1)
				element.TempLoss:SetValue(0, element.smoothing)

				if(not element.TempLoss:GetStatusBarTexture()) then
					element.TempLoss:SetStatusBarTexture('UI-HUD-UnitFrame-Target-PortraitOn-Bar-TempHPLoss')
				end
			end

			element.TempLoss:Show()
		end

		return true
	end
end

local function Disable(self)
	local element = self.Health
	if(element) then
		element:Hide()

		if(element.HealingAll) then
			element.HealingAll:Hide()
		end

		if(element.HealingPlayer) then
			element.HealingPlayer:Hide()
		end

		if(element.HealingOther) then
			element.HealingOther:Hide()
		end

		if(element.OverHealIndicator) then
			element.OverHealIndicator:Hide()
		end

		if(element.DamageAbsorb) then
			element.DamageAbsorb:Hide()
		end

		if(element.HealAbsorb) then
			element.HealAbsorb:Hide()
		end

		if(element.OverDamageAbsorbIndicator) then
			element.OverDamageAbsorbIndicator:Hide()
		end

		if(element.OverHealAbsorbIndicator) then
			element.OverHealAbsorbIndicator:Hide()
		end

		self:UnregisterEvent('UNIT_HEALTH', Path)
		self:UnregisterEvent('UNIT_MAXHEALTH', Path)
		self:UnregisterEvent('UNIT_HEAL_PREDICTION', Path)
		self:UnregisterEvent('UNIT_ABSORB_AMOUNT_CHANGED', Path)
		self:UnregisterEvent('UNIT_HEAL_ABSORB_AMOUNT_CHANGED', Path)
		self:UnregisterEvent('UNIT_MAX_HEALTH_MODIFIERS_CHANGED', Path)
		self:UnregisterEvent('UNIT_CONNECTION', Path)
		self:UnregisterEvent('PARTY_MEMBER_ENABLE', Path)
		self:UnregisterEvent('PARTY_MEMBER_DISABLE', Path)
		self:UnregisterEvent('UNIT_FACTION', ColorPath)
		self:UnregisterEvent('UNIT_FLAGS', ColorPath)
		self:UnregisterEvent('UNIT_THREAT_LIST_UPDATE', ColorPath)

		if(element.TempLoss) then
			element.TempLoss:Hide()
		end
	end
end

oUF:AddElement('Health', Path, Enable, Disable)
