-- This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
-- To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/
-- or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.
local MereHealingFrames, privateVars = ...

-- map of unitId -> panels
MereHealingFrames.UnitIdPanels = {}

MereHealingFrames.HealingPanel = {
						Frame = nil,
						Health = nil,
						ResourceBar = nil,
						Status = nil,
						ParentFrame = nil,
						ParentLayout = nil,
						Mask = nil,
						unitId = nil,
						isManaBar = true,
						spells = nil,
						curses = 0,
						poisons = 0,
						disease = 0,
						buffIcons = nil,
						debuffIcons = nil,
						hotIcons = nil,
						buffIdRemoveFunctions = nil,
						needFullPlayerState = true,
						BuffTracking = nil,
						playerInfo = nil,
						panelSettings = nil,
						ResourceHeight = 16,
						LayoutOffset = 1,
                        RoleIcon = nil,
                        currentPointX = nil,
                        currentPointY = nil,
                        currentAnchorPoint = nil,
                        currentHeight = 0,
                        currentWidth = 0,
                        isVisible = nil
						}

function MereHealingFrames.HealingPanel:new (settings, ParentLayout)
	if not ParentLayout then
		error("No ParentLayout?")
	end

	local this = settings or {}

	setmetatable(this, self)
	self.__index = self

	this:CreateUIObjects(ParentLayout)
	return this
end

function MereHealingFrames.HealingPanel:CreateUIObjects (ParentLayout)
	self.ParentLayout = ParentLayout
	self.ParentFrame = ParentLayout.Frame
	self.buffIcons = {}
	self.debuffIcons = {}
	self.buffIdRemoveFunctions = {}
	self.hotIcons = {}
	self.BuffTracking = {}

	self.curses = 0
	self.diseases = 0
	self.poisons = 0

	self.Frame = UI.CreateFrame("Texture", "Frame", self.ParentFrame)

	self.Mask = UI.CreateFrame("Frame", "mask", self.ParentFrame)
	self.Mask:SetSecureMode("restricted")
	self.Mask:SetBackgroundColor(0,0,0,0)
	self.Mask:SetVisible(false)
	self.Mask:SetPoint("TOPLEFT", self.Frame, "TOPLEFT")
    self.Mask:SetPoint("BOTTOMRIGHT", self.Frame, "BOTTOMRIGHT")

    MereHealingFrames.Debug(10, "Mask '%s' secure mode is: %s", self.Mask:GetName(), self.Mask:GetSecureMode())

    self:CreateRoleIcon()
	self:CreateNameLabel()
	self:CreateStatusMask()

    self.Absorb = UI.CreateFrame("Frame", "absorbFrame", self.Frame)
    self.Absorb:SetPoint("TOPLEFT", self.Frame, "TOPLEFT")
    self.Absorb:SetPoint("BOTTOMLEFT", self.Frame, "BOTTOMLEFT")
    self.Absorb:SetVisible(false)
    self.Absorb:SetBackgroundColor(MereHealingFrames.Colours.FetchRGBA("BarAbsorb"))

	self.Health = MereHealingFrames.HealingBar.Create({}, self.Frame)
	self.ResourceBar = MereHealingFrames.HealingBar.Create({}, self.Frame)
end

function MereHealingFrames.HealingPanel:Initialize(settings, ParentLayout, LayoutOffset)
	if not ParentLayout then
		error("No ParentLayout?")
	end

    MereHealingFrames.Debug(10, "HealingPanel:Initialize, parentFrame is '%s'", ParentLayout.Frame:GetName())
    MereHealingFrames.DebugDump(20, self.Mask)

    self.ParentLayout = ParentLayout
	self.ParentFrame = ParentLayout.Frame
	self.PanelSettings = ParentLayout.PanelSettings
	self.ResourceHeight = self.PanelSettings.ManaHeight -- setup based on calling

	self.buffIcons = {}
	self.debuffIcons = {}
	self.buffIdRemoveFunctions = {}
	self.LayoutOffset = LayoutOffset

	self.Frame:SetParent(self.ParentFrame)
	self.Frame:SetLayer(MereHealingFrames.Layers.CalculateLayer(LayoutOffset, "PanelBase"))
	self.Frame:SetBackgroundColor(MereHealingFrames.Colours.FetchRGBA("PanelBorderDefault"))

    self.Mask:SetBackgroundColor(0,0,0,0)
    self.Mask:SetVisible(false)
	self.Mask:SetParent(self.ParentFrame)
    self.Mask:SetSecureMode("restricted")
	self.Mask:SetLayer(MereHealingFrames.Layers.CalculateLayer(LayoutOffset, "MaskBase"))
    self.Mask:SetPoint("TOPLEFT", self.Frame, "TOPLEFT")
    self.Mask:SetPoint("BOTTOMRIGHT", self.Frame, "BOTTOMRIGHT")

    MereHealingFrames.Debug(5, "Mask '%s' secure mode is: %s", self.Mask:GetName(), self.Mask:GetSecureMode())

	self:InitializeRoleIcon(LayoutOffset)
	self:InitializeNameLabel(LayoutOffset)
	self:InitializeStatusMask(LayoutOffset)

    self.Absorb:SetPoint("TOPLEFT", self.Frame, "TOPLEFT")
    self.Absorb:SetPoint("BOTTOMLEFT", self.Frame, "BOTTOMLEFT")
    self.Absorb:SetVisible(false)
    self.Absorb:SetBackgroundColor(MereHealingFrames.Colours.FetchRGBA("BarAbsorb"))
    self.Absorb:SetLayer(MereHealingFrames.Layers.CalculateLayer(LayoutOffset, "AbsorbFrame"))

	self.Health:Initialize(LayoutOffset, "health")
	self.Health:Move(self.PanelSettings.borderSize, self.PanelSettings.borderSize)

	self.ResourceBar:Initialize(LayoutOffset, "mana")
	self.ResourceBar:Move(self.PanelSettings.borderSize, self.Frame:GetHeight() - self.ResourceHeight - 1)

	self:SetupHotIcons(LayoutOffset)
end

function MereHealingFrames.HealingPanel:RefreshPanelSettings()
	local panelSettings = self.PanelSettings

	self.Health:SetTextlayout(panelSettings.HealthTextFormatter, panelSettings.HealthTextRounding)

    self:ResizeBars()

	self:MoveRoleIcon(panelSettings.borderSize)

	self:SetupPlayerValues()

	self:RebuildHotIcons()
end

function MereHealingFrames.HealingPanel:SetPlayerInfo(playerInfo)
	self.playerInfo = playerInfo
	self.unitId = playerInfo.unitId

	local panels = MereHealingFrames.UnitIdPanels[self.unitId] or {}
	table.insert(panels, self)
	MereHealingFrames.UnitIdPanels[self.unitId] = panels

	self:SetupPlayerValues()

    self.Health:UpdateEvents(playerInfo.PlayerEvents.Events.health, playerInfo.PlayerEvents.Events.healthMax)

	-- TODO Secure call
	if not playerInfo.isFake then
		self.Mask:SetMouseoverUnit(self.unitId)
	end
	self:RefreshPanelSettings()

	self:SetVisible(true)
end

function MereHealingFrames.HealingPanel:RemoveUnitId()
	self:UnHookPanel()

    self:ResetHotIcons()

	self:SetVisible(false)

	self.unitId = nil
	self.playerInfo = nil

    self.currentPointX = nil
    self.currentPointY = nil
    self.currentAnchorPoint = nil
    self.currentHeight = 0
    self.currentWidth = 0
end

function MereHealingFrames.HealingPanel:UnHookPanel()
	local index = nil

    local UnitIdPanels = MereHealingFrames.UnitIdPanels[self.unitId]

	for i, panel in ipairs(UnitIdPanels) do
		if (panel == self) then
			index = i
			break
		end
	end

	if (index == nil) then
		error("Unable to unhook panel, how did we loose it?, unitId: " .. self.unitId)
	end

	table.remove(UnitIdPanels, index)
end

function MereHealingFrames.HealingPanel:SetupPlayerValues()
	MereHealingFrames.DebugDump(5, self.playerInfo)
	local playerInfo = self.playerInfo

	MereHealingFrames.Debug(5, "Starting health %d/%d", tostring(playerInfo.health), tostring(playerInfo.healthMax))
	self.Health:UpdateBar(playerInfo.health, playerInfo.healthMax)

	self.Health:SetBorderedText(self.PanelSettings.HealthTextBordered)
    self.Health:SetFontSize(self.PanelSettings.HealthFontSize)

	self:Calling()
	self:Name()
	self:UpdateAbsorb(playerInfo.absorb)

	self:Afk(playerInfo.afk)
	self:SetRole(playerInfo.role)

	--TODO secure call...
	self:UpdateSpells()
end

function MereHealingFrames.HealingPanel:SetRole(role)
    self.Health:SetRoleMode(self.PanelSettings.roleColouredHealth, role)
    return self.RoleIcon:SetRole(role)
end

function MereHealingFrames.HealingPanel:Calling()
	-- what we show varies a for the resource bar:
	local playerInfo = self.playerInfo
	local panelSettings = self.PanelSettings

	if playerInfo.calling == "unknown" then
		MereHealingFrames.Debug(5, "no known calling yet")
	elseif (playerInfo.calling == "mage" or playerInfo.calling == "cleric") then
		if panelSettings.ShowMana then
			self.ResourceBar:SetBarMode("mana")
			self.ResourceBar:UpdateBar(playerInfo.mana, playerInfo.manaMax)
            self.ResourceBar:UpdateEvents(playerInfo.PlayerEvents.Events.mana, playerInfo.PlayerEvents.Events.manaMax)
			self.ResourceBar:SetVisible(true)
			self.ResourceHeight = panelSettings.ManaHeight
			self.ResourceBar:SetTextlayout(panelSettings.ManaTextFormatter, panelSettings.ManaTextRounding)
			self.ResourceBar:SetBorderedText(panelSettings.ManaTextBordered)
            self.ResourceBar:SetFontSize(panelSettings.ManaFontSize)
		else
			self.ResourceBar:SetVisible(false)
			self.ResourceHeight = 0
            self.ResourceBar:UpdateEvents(nil, nil)
		end
	elseif (playerInfo.calling == "rogue") then
		if panelSettings.ShowEnergy then
			self.ResourceBar:SetBarMode(playerInfo.calling)
			self.ResourceBar:UpdateBar(playerInfo.energy, playerInfo.energyMax)
            self.ResourceBar:UpdateEvents(playerInfo.PlayerEvents.Events.energy, playerInfo.PlayerEvents.Events.energyMax)
			self.ResourceBar:SetVisible(true)
			self.ResourceHeight = panelSettings.EnergyHeight
			self.ResourceBar:SetTextlayout(panelSettings.EnergyTextFormatter, panelSettings.EnergyTextRounding)
			self.ResourceBar:SetBorderedText(panelSettings.EnergyTextBordered)
            self.ResourceBar:SetFontSize(panelSettings.EnergyFontSize)
		else
			self.ResourceBar:SetVisible(false)
			self.ResourceHeight = 0
            self.ResourceBar:UpdateEvents(nil, nil)
		end
	elseif (playerInfo.calling == "warrior") then
		if panelSettings.ShowEnergy then
			self.ResourceBar:SetBarMode(playerInfo.calling)
			self.ResourceBar:UpdateBar(playerInfo.power, 100) -- no unitDetails.powerMax
            self.ResourceBar:UpdateEvents(playerInfo.PlayerEvents.Events.power, nil)
			self.ResourceBar:SetVisible(true)
			self.ResourceHeight = panelSettings.EnergyHeight
			self.ResourceBar:SetTextlayout(panelSettings.EnergyTextFormatter, panelSettings.EnergyTextRounding)
			self.ResourceBar:SetBorderedText(panelSettings.EnergyTextBordered)
            self.ResourceBar:SetFontSize(panelSettings.EnergyFontSize)
		else
			self.ResourceBar:SetVisible(false)
			self.ResourceHeight = 0
            self.ResourceBar:UpdateEvents(nil, nil)
		end
	else
		error("Unknown calling: " .. playerInfo.calling)
	end
	self:ResizeBars()

	self.Health:SetCallingMode(panelSettings.callingColouredHealth, playerInfo.calling)
	self:Name()
end

function MereHealingFrames.HealingPanel:Name()
	local playerInfo = self.playerInfo
	local panelSettings = self.PanelSettings

	if (panelSettings.callingColouredText) then
		if playerInfo.calling == "unknown" then
			self.NameLabel:SetTextColourName("UnknownColour")
		elseif playerInfo.calling == "warrior" then
            self.NameLabel:SetTextColourName("WarriorColour")
		elseif playerInfo.calling == "cleric" then
            self.NameLabel:SetTextColourName("ClericColour")
		elseif playerInfo.calling == "mage" then
            self.NameLabel:SetTextColourName("MageColour")
		elseif playerInfo.calling == "rogue" then
            self.NameLabel:SetTextColourName("RogueColour")
		end
	else
        self.NameLabel:SetTextColourName("UnknownColour")
	end

	if panelSettings.borderPlayerName then
		self.NameLabel:ShadowedText(true)
	else
		self.NameLabel:ShadowedText(false)
	end

    if panelSettings.NameFontSize then
        self.NameLabel:SetFontSize(panelSettings.NameFontSize)
    end

	self.NameLabel:SetText(playerInfo.name)
	self.NameLabel:SetVisible(true)
end

function MereHealingFrames.HealingPanel:CreateNameLabel()
	self.NameLabel = MereHealingFrames.UI.Widget.ShadowedText:new("Name", self.Frame)
	self.NameLabel:SetPoint("TOPLEFT", self.Frame, "TOPLEFT")
end

function MereHealingFrames.HealingPanel:InitializeNameLabel(LayoutOffset)
	self.NameLabel:SetText("?")
	self.NameLabel:SetLayer(MereHealingFrames.Layers.CalculateLayer(LayoutOffset, "PanelName"))
end

function MereHealingFrames.HealingPanel:CreateStatusMask()
	self.StatusMask = UI.CreateFrame("Frame", "StatusMaskFrame", self.Frame)
	self.StatusText = MereHealingFrames.UI.Widget.ShadowedText:new("StatusMaskText", self.StatusMask)

	self.StatusMask:SetPoint("TOPLEFT", self.Frame, "TOPLEFT")
	self.StatusMask:SetPoint("BOTTOMRIGHT", self.Frame, "BOTTOMRIGHT")

	self.StatusText:SetPoint("CENTER", self.StatusMask, "CENTER")
	self.StatusMask:SetVisible(false)
end

function MereHealingFrames.HealingPanel:InitializeStatusMask(LayoutOffset)
	self.StatusMask:SetBackgroundColor(0,0,0,0)
	self.StatusMask:SetLayer(MereHealingFrames.Layers.CalculateLayer(LayoutOffset, "PanelStatusPanel"))
	self.StatusText:SetText("")
	self.StatusText:SetLayer(MereHealingFrames.Layers.CalculateLayer(LayoutOffset, "PanelStatusText"))
end

function MereHealingFrames.HealingPanel:RebuildHotIcons()
	self:ResetHotIcons()
	self:SetupHotIcons()
	self:HookHotIcons()
end

function MereHealingFrames.HealingPanel:ResetHotIcons()
	for i=1, 20 do
        local hotIcon = self.hotIcons[i]
		if hotIcon then
            self.playerInfo.buffMgmt:RemoveUIBuff(hotIcon, hotIcon.BuffSlot)
            MereHealingFrames.HotIconFactory.Delete(hotIcon)
		end
	end
	self.hotIcons = {}
end

function MereHealingFrames.HealingPanel:HookHotIcons()
	local buffConfiguration = self.PanelSettings.buffConfiguration
	for i=1, 20 do
		local hotIcon = self.hotIcons[i]
		if hotIcon then
			self.playerInfo.buffMgmt:AddUIBuff(hotIcon, hotIcon.BuffSlot)
		end
	end
end

function MereHealingFrames.HealingPanel:SetupHotIcons()
	local buffConfiguration = self.PanelSettings.buffConfiguration
	local slots = buffConfiguration.slots
	for i=1, 20 do
		if slots[i] > 0 then
			self.hotIcons[i] = MereHealingFrames.HotIconFactory.New(self.Frame)
			self.hotIcons[i].BuffSlot = slots[i]
            self.hotIcons[i].Name = "IconSlot " .. i
		else
			self.hotIcons[i] = false
		end
	end

	local slotPos = 1
	for i=1, buffConfiguration.topRow do
		local hotIcon = self.hotIcons[slotPos]
		if hotIcon then
			local width = (self.PanelSettings.borderSize + hotIcon.Width/2 + (hotIcon.Width * (i-1)))
			hotIcon.AnchorY = self.PanelSettings.borderSize + hotIcon.Height/2
			hotIcon.AnchorFrame = self.Frame

			if buffConfiguration.topRightToLeft then
				hotIcon.AnchorX = -width
				hotIcon.AnchorTarget = "TOPRIGHT"
			else
				hotIcon.AnchorX = width
				hotIcon.AnchorTarget = "TOPLEFT"
			end

			hotIcon:Initialize(self.LayoutOffset)
		end

		slotPos = slotPos + 1
	end

	for i=1, buffConfiguration.middleRow do
		local hotIcon = self.hotIcons[slotPos]
		if hotIcon then
			local width = (self.PanelSettings.borderSize + hotIcon.Width/2 + (hotIcon.Width * (i-1)))

			hotIcon.AnchorY = 0
			hotIcon.AnchorFrame = self.Frame

			if buffConfiguration.middleRightToLeft then
				hotIcon.AnchorX = -width
				hotIcon.AnchorTarget = "CENTERRIGHT"
			else
				hotIcon.AnchorX = width
				hotIcon.AnchorTarget = "CENTERLEFT"
			end
			hotIcon:Initialize(self.LayoutOffset)
		end

		slotPos = slotPos + 1
	end

	for i=1, buffConfiguration.bottomRow do
		local hotIcon = self.hotIcons[slotPos]
		if hotIcon then
			local width = (self.PanelSettings.borderSize + hotIcon.Width/2 + (hotIcon.Width * (i-1)))
			hotIcon.AnchorY = -(self.PanelSettings.borderSize + hotIcon.Height/2)
			hotIcon.AnchorFrame = self.Frame

			if buffConfiguration.bottomRightToLeft then
				hotIcon.AnchorX = -width
				hotIcon.AnchorTarget = "BOTTOMRIGHT"
			else
				hotIcon.AnchorX = width
				hotIcon.AnchorTarget = "BOTTOMLEFT"
			end
			hotIcon:Initialize(self.LayoutOffset)
		end

		slotPos = slotPos + 1
	end
end

function MereHealingFrames.HealingPanel:Move(topLeftX, topLeftY, parentAnchor)
    if (self.currentPointX == topLeftX and self.currentPointY == topLeftY and self.currentAnchorPoint == parentAnchor) then
        return
    end
    self.currentPointX, self.currentPointY, self.currentAnchorPoint = topLeftX, topLeftY, parentAnchor

	self.Frame:SetPoint("TOPLEFT", self.ParentFrame, parentAnchor or "TOPLEFT", topLeftX, topLeftY)
end


local clickToEventMapping = {
    LeftClick = Event.UI.Input.Mouse.Left.Click,
    RightClick = Event.UI.Input.Mouse.Right.Click,
    MiddleClick = Event.UI.Input.Mouse.Middle.Click,
    Mouse4Click = Event.UI.Input.Mouse.Mouse4.Click,
    Mouse5Click = Event.UI.Input.Mouse.Mouse5.Click,
    WheelForward = Event.UI.Input.Mouse.Wheel.Forward,
    WheelBack = Event.UI.Input.Mouse.Wheel.Back
}

function MereHealingFrames.HealingPanel:UpdateSpells()
	if not self.unitId then return end

	MereHealingFrames.Debug(4, "Updating spells for panel, unitId: %s", self.unitId)
	local castTarget = self.unitId
	local spells = MereHealingFrames.CurrentSpellSet

    local LeftClickMacro = MereHealingFrames.Spells.CreateCastMacros(spells["LeftClick"], castTarget)
    MereHealingFrames.Debug(10, "LeftClickMacro: %s", LeftClickMacro)

	self.Mask:EventMacroSet(Event.UI.Input.Mouse.Left.Click, LeftClickMacro)
    self.Mask:EventMacroSet(Event.UI.Input.Mouse.Right.Click, MereHealingFrames.Spells.CreateCastMacros(spells["RightClick"], castTarget))
    self.Mask:EventMacroSet(Event.UI.Input.Mouse.Middle.Click, MereHealingFrames.Spells.CreateCastMacros(spells["MiddleClick"], castTarget))
    self.Mask:EventMacroSet(Event.UI.Input.Mouse.Mouse4.Click, MereHealingFrames.Spells.CreateCastMacros(spells["Mouse4Click"], castTarget))
    self.Mask:EventMacroSet(Event.UI.Input.Mouse.Mouse5.Click, MereHealingFrames.Spells.CreateCastMacros(spells["Mouse5Click"], castTarget))
    self.Mask:EventMacroSet(Event.UI.Input.Mouse.Wheel.Forward, MereHealingFrames.Spells.CreateCastMacros(spells["WheelForward"], castTarget))
    self.Mask:EventMacroSet(Event.UI.Input.Mouse.Wheel.Back, MereHealingFrames.Spells.CreateCastMacros(spells["WheelBack"], castTarget))
    self.Mask:EventAttach(Event.UI.Input.Mouse.Cursor.In, function () MereHealingFrames.ToolTip.Show(self) end, "tooltipShow")
    self.Mask:EventAttach(Event.UI.Input.Mouse.Cursor.Out, function () MereHealingFrames.ToolTip.Hide() end, "tooltipHide")
    self.Mask:SetMouseMasking("limited")
    MereHealingFrames.DebugDump(20, self.Mask);
end

function MereHealingFrames.HealingPanel:GetToolTipText()
	local uglyLongTT = 	self:GetToolTipButtonText("Left Click:\n\t", "LeftClick") ..
						self:GetToolTipButtonText("Right Click:\n\t", "RightClick") ..
						self:GetToolTipButtonText("Middle Click:\n\t", "MiddleClick") ..
						self:GetToolTipButtonText("Mouse 4 Click:\n\t", "Mouse4Click") ..
						self:GetToolTipButtonText("Mouse 5 Click:\n\t", "Mouse5Click") ..
						self:GetToolTipButtonText("Wheel Forward/Up:\n\t", "WheelForward") ..
						self:GetToolTipButtonText("Wheel Back/Down:\n\t", "WheelBack")
	return uglyLongTT
end

function MereHealingFrames.HealingPanel:GetToolTipButtonText(buttonText, eventName)
	local eventText = self.Mask:EventMacroGet(clickToEventMapping[eventName])
	if eventText then
		return buttonText .. eventText
	end
	return ""
end

function MereHealingFrames.HealingPanel:Resize(width, height)
    if (self.currentWidth == width and self.currentHeight == height) then
        return
    end

    self.currentWidth, self.currentHeight = width, height

	self.Frame:SetWidth(width)
	self.Frame:SetHeight(height)

	self:ResizeBars()
end

--- TODO: Can this be optimized away with careful anchoring?
function MereHealingFrames.HealingPanel:ResizeBars()
	local width, height = self.currentWidth, self.currentHeight

	self.Health:Move(self.PanelSettings.borderSize, self.PanelSettings.borderSize)
	self.ResourceBar:Move(self.PanelSettings.borderSize, height - self.ResourceHeight - self.PanelSettings.borderSize)

	self.Health:Resize(width - (self.PanelSettings.borderSize * 2), height - self.ResourceHeight - (self.PanelSettings.borderSize * 2))
	self.ResourceBar:Resize(width - (self.PanelSettings.borderSize * 2), self.ResourceHeight)

	self.NameLabel:SetWidth(width - 16 - (self.PanelSettings.borderSize * 2))
end

function MereHealingFrames.HealingPanel:UpdateAbsorb(value)
    --self.ResourceBar:UpdateBar(nil, value)
    if (value and self.PanelSettings.absorbShown) then
        local playerInfo = self.playerInfo
        local absorbPercent = math.min(1, value/playerInfo.healthMax)
        self.Absorb:SetWidth(absorbPercent * self.Frame:GetWidth())
        self.Absorb:SetVisible(true)
        MereHealingFrames.Debug(6, "new absorb value %d", value)
    else
        self.Absorb:SetVisible(false)
        MereHealingFrames.Debug(6, "absorb cleared")
    end
end

function MereHealingFrames.HealingPanel:Afk(isAfk)
	if (isAfk) then
		self.NameLabel:SetText(self.playerInfo.name .. " (AFK)")
	else
		self.NameLabel:SetText(self.playerInfo.name)
	end
end

function MereHealingFrames.HealingPanel:StatusChange()
	local playerInfo = self.playerInfo

	self:SetMessage("", false)

	if playerInfo.aggro then
		self.Frame:SetBackgroundColor(MereHealingFrames.Colours.FetchRGBA("PanelBorderAggro"))
	elseif playerInfo.blocked then
		self.Frame:SetBackgroundColor(MereHealingFrames.Colours.FetchRGBA("PanelBorderBlocked"))
		self:SetMessage("Blocked", true, 0.3)
	else
		self.Frame:SetBackgroundColor(MereHealingFrames.Colours.FetchRGBA("PanelBorderDefault"))
	end

	if playerInfo.dead then
		self:SetMessage("Dead", true, 0.8)
	elseif playerInfo.offline then
		self:SetMessage("Offline", true, 0.8)
	elseif playerInfo.inRange ~= nil and not playerInfo.inRange then
		self:SetMessage("Out of range", not playerInfo.inRange, 0.6)
	end
end

function MereHealingFrames.HealingPanel:GroupLeave()
	self.hasLeft = true
	self:SetMessage("Left group", self.hasLeft)
	self.Frame:SetBackgroundColor(0,0,0,1)
end

function MereHealingFrames.HealingPanel:SetMessage(text, showMask, alphaLevel)
	self.StatusText:SetText(text)
	self.StatusMask:SetBackgroundColor(0,0,0, alphaLevel or 0.5)
	self.StatusMask:SetVisible(showMask or false)
end

function MereHealingFrames.HealingPanel:SetVisible(visible)
    if (self.isVisible == visible) then
        return
    end
    self.isVisible = visible

	self.Frame:SetVisible(visible)
    self.Mask:SetVisible(visible)

    if (visible) then
	    self:StatusChange()
    end
end