Quantcast
-- HealWatchFrames.lua
-- This file controls the creation and management of dynamic frames.
-- all variables with a _ at the beginning are local
-- full credits go to wereHamster aka Shag for the frame creation lua

-- reference to my name
local _playerName = nil
-- reference to the very last frame, where we insert things
local _pFrame = HealWatchCastFrame
-- reference to the very first frame, in case we remove it, we'll know.
local _headFrame = nil
-- table of free label frames
local _freeLabels = {}
-- table of free cast bar frames
local _freeBars = {}
-- table of name -> frame
local _frames = {}
-- shortcuts for table.getn(_freeLabels) and _freeBars
local _labelsFree,_barsFree = 0,0
-- local reference to the heals
local _Heals = HealWatch._Heals
-- single instance for coloring variables to help cut down on wasted memory
local _color,_text,_colorTbl = nil,nil,{}
-- table of all label frames
local _labelFrames = {}
-- table of all bar frames
local _barFrames = {}
-- number of bars used, to check agoinst max cast bars
local _barsUsed = 0
-- shortcut for HealWatchCastFrame:GetHeight() so we don't keep calling it
local _height,_width = 32,210
-- table of que'd heals when there are too many.
local _healQue = {}
local _backdropTableLabelFrame = {
	bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
	edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
	tile = true,
	tileSize = 16,
	edgeSize = 16,
	insets = {
		left = 1,
		right = 1,
		top = 1,
		bottom = 1
	}
}
if (not CASTING_BAR_ALPHA_STEP) then CASTING_BAR_ALPHA_STEP = 0.05 end
if (not CASTING_BAR_FLASH_STEP) then CASTING_BAR_FLASH_STEP = 0.2 end
if (not CASTING_BAR_HOLD_TIME) then CASTING_BAR_HOLD_TIME = 1 end

local _currentLastFrame


-- for sticky frame
local _stickFrame,prevFrame
_playerName = HealWatch._playerName
local function _CreateLabelFrame(target,lock)
	local width = HealWatch.Options.labelWidth
	local frame = CreateFrame('Button','HealWatchLabelFrame'..table.getn(_labelFrames) + 1)
	frame:SetHeight(24)
	frame:SetWidth(width)
	frame:SetBackdrop(_backdropTableLabelFrame)
	frame:SetBackdropColor(0, 0, 0, 0.75)
	frame:SetParent(HealWatchCastFrame)

	local health = frame:CreateFontString(nil,"ARTWORK")
	health:Show()
	health:SetFontObject(GameFontHighlight)
	health:SetWidth(math.floor(0.25*width))
	health:SetHeight(24)
	health:ClearAllPoints()
	health:SetPoint('RIGHT',frame,'RIGHT',-8,1)
	health:SetJustifyH('RIGHT')
	health:SetParent(frame)
	frame.health = health

	local check = CreateFrame('CheckButton')
	check:SetHeight(16)
	check:SetWidth(16)
	check:Show()
	check:ClearAllPoints()
	check:SetPoint('TOPLEFT',frame,'TOPLEFT',4,-4)
	check:SetNormalTexture('Interface\\Buttons\\UI-CheckBox-Up')
	check:SetPushedTexture('Interface\\Buttons\\UI-CheckBox-Down')
	check:SetHighlightTexture('Interface\\Buttons\\UI-CheckBox-Highlight')
	check:SetCheckedTexture('Interface\\Buttons\\UI-CheckBox-Check')
	check:SetDisabledTexture('Interface\\Buttons\\UI-CheckBox-Check-Disable')
	check:SetParent(frame)
	frame.check = check

	local text = frame.check:CreateFontString(nil,'ARTWORK')
	text:Show()
	text:ClearAllPoints()
	text:SetJustifyH("LEFT")
	text:SetPoint('LEFT',frame.check,'RIGHT',-2,0)
	text:SetWidth(math.floor(0.75*width)-16)
	text:SetFontObject(GameFontNormalSmall)
	text:SetText(target)
	frame.text = text

	if (HealWatch.LabelCheckOnClick) then frame.check:SetScript('OnClick',function() HealWatch.LabelCheckOnClick(arg1) end) end
	if (HealWatch.LabelOnClick) then frame:SetScript('OnClick',function() HealWatch.LabelOnClick(arg1) end) end
	--frame:RegisterForClicks('RightButtonDown') -- uncomment the beginning of this line for menu only operation
	frame:RegisterForClicks('LeftButtonDown','RightButtonDown')
	frame:RegisterForDrag('LeftButton')
	frame:SetScript('OnDragStart',function()
		if (this.detached) then
			this:StartMoving()
		else
			HealWatchAnchorFrame:StartMoving()
		end
	end)
	frame:SetScript('OnDragStop',function()
		if (this.detached) then
			this:StartMoving()
		else
			HealWatchAnchorFrame:StopMovingOrSizing()
			HealWatch.SavePosition()
		end
	end)
	frame:SetMovable(true)

	table.insert(_labelFrames,frame)
	frame.inUse = true
	frame.castBars = {}
	frame.offset = 0
	return frame
end

function HealWatch.SavePosition()
    local f = HealWatchAnchorFrame
    local x,y = f:GetLeft(), f:GetTop()
    local s = f:GetEffectiveScale()

    x,y = x*s,y*s

    HealWatchSave.frameX = x
    HealWatchSave.frameY = y
end

function HealWatch.RestorePosition()
    local x = HealWatchSave.frameX
    local y = HealWatchSave.frameY

    local f = HealWatchAnchorFrame
    local s = f:GetEffectiveScale()

    if not x or not y then
        f:ClearAllPoints()
        f:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
        return
    end

    x,y = x/s,y/s

    f:ClearAllPoints()
    f:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", x, y)
end

function HealWatch.RemLabelFrame(frame)
	-- if it is locked, don't remove it
	if (not frame or frame.locked) then return end
	-- make sure the frame has a target and is in use
	if (not frame.inUse or not frame.target) then
		HealWatch.FreeLabelFrame(frame)
		return
	end
	-- if it has a cast bar and we want to show all heals, don't remove it
	if (frame.lastBar and frame.lastBar ~= frame) then
		-- if we are showing all heals, don't remove the frame
		if (HealWatch.Options.showAllHeals) then return end
		-- otherwise, iterate through the frames and remove them
		local castBar
		while (frame.lastBar and frame.lastBar ~= frame) do
			castBar = frame.lastBar
			HealWatch.RemCastBar(castBar)
		end
	end
	if (HealWatch.dframe and HealWatch.debugSetHeight) then
		HealWatch.dframe:AddMessage('RemLabelFrame: Calling SetHeight: '.._height..' for target: '..frame.target)
	end
	-- remove the frame from the lists
	if (frame.target and _frames[frame.target] == frame) then
		_frames[frame.target] = nil
		frame.target = nil
	end
	-- if the last frame is this frame. then set the last frame to the previous frame
	if (_pFrame == frame) then _pFrame = frame.pFrame end
	-- if there is not a last frame or it is the main frame, then show the HW label
	if (not _pFrame or _pFrame == HealWatchCastFrame) then
		local frame2 = HealWatchLabelHeader
		frame2:Show()
		HealWatch.SetFrame(frame2,HealWatchCastFrame)
	end
	-- if the headFrame is this frame, then set the headframe to the next frame (should be a label)
	if (_headFrame == frame) then _headFrame = frame.nFrame end
	-- if there is no headframe, then show the HW label frame
	if (not _headFrame or _headFrame == HealWatchCastFrame) then
		local frame2 = HealWatchLabelHeader
		frame2:Show()
		HealWatch.SetFrame(frame2,HealWatchCastFrame)
	end
	-- if we have a previous frame then
	if (frame.pFrame) then
		-- debug
		if (HealWatch.dframe and HealWatch.debugRemLabelFrame) then
			HealWatch.dframe:AddMessage('RemLabelFrame: frame has a pFrame: '..frame:GetName())
		end
		-- if we have a next frame
		if (frame.nFrame) then
			-- set the next frame's previous frame to this frame's previous frame
			frame.nFrame.pFrame = frame.pFrame
			-- set the points of the next frame
			HealWatch.SetFrame(frame.nFrame,frame.pFrame)
		end
		-- set the previous frame's next frame to this frame's next frame
		frame.pFrame.nFrame = frame.nFrame
	else
		-- otherwise see if we have a next frame
		if (frame.nFrame) then
			-- if we do, then set the next frame's previous to this frame's previous
			frame.nFrame.pFrame = frame.pFrame
			-- set the points with the main frame as the previous frame
			HealWatch.SetFrame(frame.nFrame,HealWatchCastFrame)
		end
	end
	-- debugging
	if (HealWatch.dframe and HealWatch.debugRemLabelFrame) then
		HealWatch.dframe:AddMessage('RemLabelFrame: removing: '..frame:GetName())
	end
	if (HealWatch.Options.LabelGrowDirection == 1 or HealWatch.Options.LabelGrowDirection == 2) then
		-- update the height
		_height = max( _height - 24,32)
		-- set the height of the main frame
		HealWatchCastFrame:SetHeight(_height)
	else
		-- set the width + 5 for that extra nudge factor
		_width = max(_width - HealWatch.Options.labelWidth,HealWatch.Options.labelWidth + 6)
		-- set the width of the main frame
		HealWatchCastFrame:SetWidth(_width)
	end
	HealWatch.FreeLabelFrame(frame)
end

function HealWatch.FreeLabelFrame(frame)
	if (not frame) then return end
	if (HealWatch.dframe and HealWatch.debugFreeLabelFrame) then
		HealWatch.dframe:AddMessage("FreeLabelFrame called: removing a frame, ".._labelsFree.." labels free now")
	end
	frame:ClearAllPoints()
	frame.pFrame = nil
	frame.lastBar = nil
	frame.nFrame = nil
	frame.inUse = false
	frame.target = nil
	frame.detached = false
	frame.lastBar = frame
	frame.unit = nil
	table.insert(_freeLabels,frame)
	_labelsFree = table.getn(_freeLabels)
	frame:Hide()
end

function HealWatch.GetLabelFrame(name)
	if (name) then
		return _frames[name]
	else
		if (not _freeLabels or _labelsFree == 0) then
			return _CreateLabelFrame()
		else
			local frame = table.remove(_freeLabels)
			_labelsFree = table.getn(_freeLabels)
			frame.inUse = true
			return frame
		end
	end
end

function HealWatch.AddLabelFrame(target,lock)
	if (HealWatch.dframe and HealWatch.debugAddLabelFrame) then
		HealWatch.dframe:AddMessage('AddLabelFrame: Called with target: '..target)
	end
	if (not target or _frames[target]) then return end
	local lframe = HealWatch.GetLabelFrame()
	if (lframe) then
		-- set up the data portion of the 'linked list node'
		lframe.text:SetText(target)
		lframe.text:SetJustifyH('LEFT')
		lframe.target = target
		lframe.unit = HealWatch.GetUnitFromName(target)
		-- check the check if it is locked
		lframe.check:SetChecked(lock)
		-- a reference to the lastBar, used in the castbar
		lframe.lastBar = lframe
		-- update the reference table for this target to be this frame
		_frames[target] = lframe
		-- if there is no last frame or the last frame is the main window, update the
		-- last frame to be this frame and remove the HW label frame
		if (not _pFrame or _pFrame == HealWatchCastFrame) then
			-- set the last frame to be the main frame
			_pFrame = HealWatchCastFrame
			-- hide the HW label frame
			HealWatchLabelHeader:Hide()
			-- set the top frame to be this frame
			_headFrame = lframe
		else
			-- otherwise there was a last frame so update the height
			if (HealWatch.Options.LabelGrowDirection == 1 or HealWatch.Options.LabelGrowDirection == 2) then
				_height = _height+24
				-- set the height of the main frame
				HealWatchCastFrame:SetHeight(_height)
			else
				_width = _width + HealWatch.Options.labelWidth
				-- set the height of the main frame
				HealWatchCastFrame:SetWidth(_width)
			end
			-- debug
			if (HealWatch.dframe and HealWatch.debugSetHeight) then
				HealWatch.dframe:AddMessage('AddLabelFrame: Calling SetHeight: '.._height)
			end
		end
		-- set the points of the frame
		HealWatch.SetFrame(lframe,_pFrame.rFrame)
		-- set the previous frame to the last frame
		lframe.pFrame = _pFrame
		-- set the last frame's next frame to this frame
		_pFrame.nFrame = lframe
		-- set the last frame to be this frame
		_pFrame = lframe
		-- set this frame as it's own reference
		lframe.rFrame = lframe
		-- show this frame
		lframe:Show()
		-- for every heal we know about, add the cast bar
		if (_Heals and _Heals.Casting and _Heals.Casting[target]) then
			local heal
			for i=1,table.getn(_Heals.Casting[target]) do
				heal = _Heals.Casting[target][i]
				HealWatch.AddCastBar(heal)
			end
		end
		-- more debugging
		if (HealWatch.dframe and HealWatch.debugAddLabelFrame) then
			HealWatch.dframe:AddMessage('AddLabelFrame: Adding new frame: '..lframe:GetName())
		end
	end
end

function HealWatch.InsertCastBar(target,castBar)
	local labelFrame = _frames[target]
	if (not labelFrame) then
		if (HealWatch.Options.showAllHeals) then HealWatch.InsertLabelFrame(target) end
		if (HealWatch.Options.showMyHeals and castBar.unit == "player") then HealWatch.InsertLabelFrame(target) end
		labelFrame = _frames[target]
		if (not labelFrame) then return end
	end
	local nextLabelFrame = labelFrame.next
	local currentOffset = labelFrame.offset
	castBar:ClearAllPoints()
	castBar:SetPoint("TOPLEFT",labelFrame,"BOTTOMLEFT",5,currentOffset)
	castBar.labelFrame = labelFrame
	castBar.offset = currentOffset
	labelFrame['castBars'][castBar] = currentOffset
	currentOffset = currentOffset-20
	labelFrame.offset = currentOffset
	_height = _height+24
	-- set the height of the main frame
	HealWatchCastFrame:SetHeight(_height)
	if (nextLabelFrame) then
		nextLabelFrame:ClearAllPoints()
		nextLabelFrame:SetPoint("TOPLEFT",labelFrame,"BOTTOMLEFT",0,currentOffset)
	end
end

function HealWatch.RemoveCastBar(target,castBar)
	local foundAnotherBar = false
	if (not castBar.labelFrame) then return end
	local labelFrame = castBar.labelFrame
	labelFrame['castBars'][castBar] = nil
	local offset = castBar.offset
	local currentOffset = labelFrame.offset
	currentOffset = currentOffset + 20
	labelFrame.offset = currentOffset
	for cBar,cOff in pairs(labelFrame['castBars']) do
		foundAnotherBar = true
		if (cOff < offset) then
			cBar:ClearAllPoints()
			cOff = cOff + 20
			cBar.offset = cOff
			cBar:SetPoint("TOPLEFT",labelFrame,"BOTTOMLEFT",5,cOff)
		end
	end
	local nextLabelFrame = labelFrame.next
	if (nextLabelFrame) then
		nextLabelFrame:ClearAllPoints()
		nextLabelFrame:SetPoint("TOPLEFT",labelFrame,"BOTTOMLEFT",0,currentOffset)
	end
	_height = _height-24
	-- set the height of the main frame
	HealWatchCastFrame:SetHeight(_height)
	-- no more castbars
	if (not foundAnotherBar and UnitName('target') ~= target) then
		HealWatch.RemoveLabelFrame(target,true)
	end
end

function HealWatch.RemoveLabelFrame(target,checkLocked)
	local labelFrame = _frames[target]
	if (not labelFrame) then return end
	if (checkLocked and labelFrame.locked) then return end
	if (HealWatch.Options.showAllHeals) then if (next(labelFrame['castBars'])) then return end end
	if (HealWatch.Options.showMyHeals) then
		found = false
		for cBar,offset in pairs(labelFrame['castBars']) do
			if (cBar.unit == "player") then found = true end
		end
		if (found) then return end
	end
	labelFrame.shown = nil
	--DevTools_Dump("RemoveLabelFrame called with target: "..tostring(target))
	local lNext = labelFrame.next
	local lPrev = labelFrame.prev
	local currentOffset = lPrev.offset
	if (lNext) then
		local point,rTo,rP,xO,yO = labelFrame:GetPoint()
		if (point) then
			lNext:ClearAllPoints()
			lNext:SetPoint(point,rTo,rP,xO,yO)
		end
		lPrev.next = lNext
		lNext.prev = lPrev
	end
	labelFrame.next = nil
	labelFrame.prev = nil
	labelFrame:ClearAllPoints()
	labelFrame:Hide()
	labelFrame.unit = nil
	tinsert(_freeLabels,labelFrame)
	_frames[target] = nil
	if (_currentLastFrame == labelFrame) then
		--DevTools_Dump("RemoveLabelFrame was the last frame!")
		if (lPrev == HealWatchCastFrame) then
			--DevTools_Dump("RemoveLabelFrame was the only frame!")
			HealWatchLabelHeader:Show()
			_currentLastFrame = nil
		else
			_currentLastFrame = lPrev
			_height = _height-24
			-- set the height of the main frame
			HealWatchCastFrame:SetHeight(_height)
		end
	else
		-- it's not the last frame so we need to update the size
		if (lPrev == HealWatchCastFrame) then
			--DevTools_Dump("RemoveLabelFrame was the first frame!")
		end
		_height = _height-24
		-- set the height of the main frame
		HealWatchCastFrame:SetHeight(_height)
	end
end

function HealWatch.InsertLabelFrame(target,lock)
	if (not target) then return end
	if (not _frames[target]) then
		_frames[target] = tremove(_freeLabels) or _CreateLabelFrame(target,lock)
	end
	local lframe = _frames[target]
	if (lframe) then
		--DevTools_Dump("InsertLabelFrame called with target: "..tostring(target))
		lframe.unit = HealWatch.GetUnitFromName(target)
		lframe.text:SetText(target)
		if (lframe.shown) then return end
		lframe.unit = HealWatch.GetUnitFromName(target)
		lframe.prev = _currentLastFrame
		-- no last frame means there was no previous frame? which means it is the first frame...
		if (not _currentLastFrame) then
			lframe:ClearAllPoints()
			lframe:SetPoint("TOPLEFT",HealWatchCastFrame,"TOPLEFT",3,-4)
			lframe.prev = HealWatchCastFrame
			HealWatchCastFrame.offset = -5
			HealWatchCastFrame.next = lframe
			HealWatchLabelHeader:Hide()
			--DevTools_Dump("InsertLabelFrame is the first frame!")
		elseif (_currentLastFrame ~= lframe) then
			_currentLastFrame.next = lframe
			lframe:ClearAllPoints()
			lframe:SetPoint("TOPLEFT",_currentLastFrame,"BOTTOMLEFT",0,_currentLastFrame.offset)
			_height = _height+24
			-- set the height of the main frame
			HealWatchCastFrame:SetHeight(_height)
		end
		_currentLastFrame = lframe
		lframe.shown = true
		lframe:Show()
	end
end

--[[function HealWatch.SetStickyTarget(target)
	if (true) then return end
	if (not _stickFrame) then
		_stickFrame = HealWatch.GetLabelFrame()
		_stickFrame:SetPoint('CENTER',UIParent,'CENTER')
		_stickFrame.detached = true
		_stickFrame.lastBar = _stickFrame
	end
	if (_stickFrame.target ~= target and _stickFrame.target) then
		DevTools_Dump('reset the frame')
		_frames[_stickFrame.target] = prevFrame
		_stickFrame.target = nil
		prevFrame = nil
	end
	if (not target) then
		_stickFrame:Hide()
		return
	end
	-- steal the frame for the target (for new heals)
	prevFrame = _frames[target]
	_frames[target] = _stickFrame
	_stickFrame.target = target
	_stickFrame.text:SetText(target)
	_stickFrame:Show()
	if (_Heals and _Heals.Casting and _Heals.Casting[target]) then
		local heal
		for i=1,table.getn(_Heals.Casting[target]) do
			heal = _Heals.Casting[target][i]
			HealWatch.AddCastBar(heal)
		end
	end
end]]--

function HealWatch.UpdateStickyTarget()
	--HealWatch.SetStickyTarget()
end

function HealWatch.AttachFrame(frame)
	if (not frame) then return end
	frame:ClearAllPoints()
	frame.detached = false
	if (HealWatch.dframe and HealWatch.debugAddLabelFrame) then
		HealWatch.dframe:AddMessage('AttachFrame: Called')
	end
	-- if there is no last frame or the last frame is the main window, update the
	-- last frame to be this frame and remove the HW label frame
	if (not _pFrame or _pFrame == HealWatchCastFrame) then
		-- set the last frame to be the main frame
		_pFrame = HealWatchCastFrame
		-- hide the HW label frame
		HealWatchLabelHeader:Hide()
		-- set the top frame to be this frame
		_headFrame = frame
	else
		-- otherwise there was a last frame so update the height
		if (HealWatch.Options.LabelGrowDirection == 1 or HealWatch.Options.LabelGrowDirection == 2) then
			_height = _height+24
			-- set the height of the main frame
			HealWatchCastFrame:SetHeight(_height)
		else
			_width = _width + HealWatch.Options.labelWidth
			-- set the height of the main frame
			HealWatchCastFrame:SetWidth(_width)
		end
	end
	-- set the points of the frame
	HealWatch.SetFrame(frame,_pFrame.rFrame)
	-- set the previous frame to the last frame
	frame.pFrame = _pFrame
	-- set the last frame's next frame to this frame
	_pFrame.nFrame = frame
	-- set the last frame to be this frame
	_pFrame = frame
	-- set this frame as it's own reference
	-- show this frame
	frame:Show()
end

function HealWatch.DetachFrame(frame)
	if (not frame) then return end
	-- make sure the frame has a target and is in use
	if (not frame.inUse or not frame.target) then
		HealWatch.FreeLabelFrame(frame)
		return
	end
	if (HealWatch.dframe and HealWatch.debugSetHeight) then
		HealWatch.dframe:AddMessage('DetachFrame: Calling SetHeight: '.._height..' for target: '..frame.target)
	end
	-- if the last frame is this frame. then set the last frame to the previous frame
	if (_pFrame == frame) then _pFrame = frame.pFrame end
	-- if there is not a last frame or it is the main frame, then show the HW label
	if (not _pFrame or _pFrame == HealWatchCastFrame) then
		local frame2 = HealWatchLabelHeader
		frame2:Show()
		HealWatch.SetFrame(frame2,HealWatchCastFrame)
	end
	-- if the headFrame is this frame, then set the headframe to the next frame (should be a label)
	if (_headFrame == frame) then _headFrame = frame.nFrame end
	-- if there is no headframe, then show the HW label frame
	if (not _headFrame or _headFrame == HealWatchCastFrame) then
		local frame2 = HealWatchLabelHeader
		frame2:Show()
		HealWatch.SetFrame(frame2,HealWatchCastFrame)
	end
	-- if we have a previous frame then
	if (frame.pFrame) then
		-- debug
		if (HealWatch.dframe and HealWatch.debugRemLabelFrame) then
			HealWatch.dframe:AddMessage('RemLabelFrame: frame has a pFrame: '..frame:GetName())
		end
		-- if we have a next frame
		if (frame.nFrame) then
			-- set the next frame's previous frame to this frame's previous frame
			frame.nFrame.pFrame = frame.pFrame
			-- set the points of the next frame
			HealWatch.SetFrame(frame.nFrame,frame.pFrame)
		end
		-- set the previous frame's next frame to this frame's next frame
		frame.pFrame.nFrame = frame.nFrame
	else
		-- otherwise see if we have a next frame
		if (frame.nFrame) then
			-- if we do, then set the next frame's previous to this frame's previous
			frame.nFrame.pFrame = frame.pFrame
			-- set the points with the main frame as the previous frame
			HealWatch.SetFrame(frame.nFrame,HealWatchCastFrame)
		end
	end
	-- debugging
	if (HealWatch.dframe and HealWatch.debugRemLabelFrame) then
		HealWatch.dframe:AddMessage('DetachFrame: removing: '..frame:GetName())
	end
	if (HealWatch.Options.LabelGrowDirection == 1 or HealWatch.Options.LabelGrowDirection == 2) then
		-- update the height
		_height = max( _height - 24,32)
		-- set the height of the main frame
		HealWatchCastFrame:SetHeight(_height)
	else
		-- set the width + 5 for that extra nudge factor
		_width = max(_width - HealWatch.Options.labelWidth,HealWatch.Options.labelWidth + 6)
		-- set the width of the main frame
		HealWatchCastFrame:SetWidth(_width)
	end
	frame.detached = true
	frame:ClearAllPoints()
	frame:SetPoint('CENTER',UIParent,'CENTER')
end

local function HealWatch_RGBToRGB_Stub( depletion, full, percent_full )
-- * 2 to try to help with the brightness. this *should* result is *almost* the same color scheme as 3.2
	_color = abs( full - depletion ) * 2
	if full ~= depletion then
		if full > depletion then
			_color = _color * percent_full
		else
			_color = _color * (1 - percent_full)
		end
		-- instead of just return color, this is to try to fix the brightness issues.
		return max(min(_color, 1), 0)
	else
		return full
	end
end

-- shamefully stolen from CastParty.  All credits go to them
function HealWatch.RGBToRGB( depletion, full, percent_full, colorTbl)

	if (not (depletion and full and percent_full and colorTbl)) then return end

	colorTbl.r = HealWatch_RGBToRGB_Stub( depletion.r, full.r, percent_full )
	colorTbl.g = HealWatch_RGBToRGB_Stub( depletion.g, full.g, percent_full )
	colorTbl.b = HealWatch_RGBToRGB_Stub( depletion.b, full.b, percent_full )
end

function HealWatch.UpdateHealth(target,hcur,hmax,hdef)
	if (_frames[target]) then
		local frame = _frames[target]
		if (HealWatch.Options.showHealth) then
			_text = hdef
			frame.health:SetText(_text)
			HealWatch.RGBToRGB(HealWatch.Options.colorHealthNone,HealWatch.Options.colorHealthFull,hcur/hmax or 0,_colorTbl)
			if (_colorTbl) then frame.health:SetTextColor(_colorTbl.r,_colorTbl.g,_colorTbl.b) end
			_text = nil
		end
	end
end

function HealWatch.AddLockedTarget(name)
	if (not name) then return end
	if (not targets) then targets = {} end
	if (not targets.locked) then targets.locked = {} end
	if (not targets.locked.hash) then targets.locked.hash = "" end
	if ( string.find(targets.locked.hash,name..":")) then return end
	table.insert(targets.locked,name)
	targets.locked.hash = targets.locked.hash..name..":"
	if (debugging) then
		dframe:AddMessage("Updated locked targets to: "..targets.locked.hash)
	end
end

function HealWatch.RemLockedTarget(name)
	if (not name) then return end
	if (not targets) then targets = {} end
	if (not targets.locked) then targets.locked = {} end
	if (not targets.locked.hash) then targets.locked.hash = "" end
	if (not string.find(targets.locked.hash,name..":")) then return end
	for i = 1,table.getn(targets.locked) do
		if (targets.locked[i] == name) then
			table.remove(targets.locked,i)
		end
	end
	targets.locked.hash = string.gsub(targets.locked.hash,name..":","")
	if (HealWatch.dframe and HealWatch.debugLockedTargets) then
		HealWatch.dframe:AddMessage("Updated locked targets to: "..targets.locked.hash)
	end
	if (HealWatch.target ~= name) then HealWatch.RemoveLabelFrame(name) end
	--[[if (HealWatch.GetLabelFrame(name) and HealWatch.target ~= name) then
		local frame = HealWatch.GetLabelFrame(name)
		if (_Heals and _Heals.Casting and _Heals.Casting[name]) then
			for i=1,table.getn(_Heals.Casting[name]) do
				local heal = _Heals.Casting[target][i]
				HealWatch.RemCastBar(heal.frame)
			end
		end
		HealWatch.RemLabelFrame(frame)
	end]]--
end

function HealWatch.ResetBars()
	if (not _headFrame) then
		local frame = HealWatchLabelHeader
		if (HealWatch.dframe and HealWatch.debugRemLabelFrame) then
			HealWatch.dframe:AddMessage('ResetBars: Showing the header')
		end
		frame:Show()
		frame:ClearAllPoints()
		HealWatch.SetFrame(frame,HealWatchCastFrame)
		if (HealWatch.dframe and HealWatch.debugSetHeight) then
			HealWatch.dframe:AddMessage('ResetBars: Calling SetHeight')
		end
		if (HealWatch.Options.LabelGrowDirection == 1 or HealWatch.Options.LabelGrowDirection == 2) then
			-- update the height
			_height = 32
			-- set the height of the main frame
			HealWatchCastFrame:SetHeight(_height)
		else
			-- set the width + 5 for that extra nudge factor
			_width = HealWatch.Options.labelWidth + 6
			-- set the width of the main frame
			HealWatchCastFrame:SetWidth(_width)
		end
		return
	end
	local frame = _headFrame
	local pFrame = HealWatchCastFrame
	local i = 0
	HealWatch.SetFrame(frame,pFrame.rFrame)
	pFrame = frame
	frame = frame.nFrame
	while (frame) do
		HealWatch.SetFrame(frame,pFrame.rFrame)
		pFrame = frame
		frame = frame.nFrame
	end
	if (HealWatch.dframe and HealWatch.debugSetHeight) then
		HealWatch.dframe:AddMessage('ResetBars: Calling SetHeight')
	end
	if (HealWatch.Options.LabelGrowDirection == 1 or HealWatch.Options.LabelGrowDirection == 2) then
		-- update the height
		_height = max((table.getn(_labelFrames)-_labelsFree)*42+(table.getn(_barFrames)-_barsFree)*20,32)
		-- set the height of the main frame
		HealWatchCastFrame:SetHeight(_height)
	else
		-- update the height
		_height = max((table.getn(_barFrames)-_barsFree)*20,32)
		-- set the height of the main frame
		HealWatchCastFrame:SetHeight(_height)
		-- set the width + 5 for that extra nudge factor
		_width = max((table.getn(_labelFrames)-_labelsFree)*HealWatch.Options.labelWidth + 6,HealWatch.Options.labelWidth+6)
		-- set the width of the main frame
		HealWatchCastFrame:SetWidth(_width)
	end
end

function HealWatch.SetFrame(frame,pFrame)
	if (not pcall(HealWatch.SetFrame2,frame,pFrame)) then
	--if (true) then return end
		DEFAULT_CHAT_FRAME:AddMessage('BUG IN HEALWATCH! RECOVERING!')
		HealWatch.ResetFrames()
	end
end

function HealWatch.SetFrame2(frame,pFrame)
	if (not frame) then return end
	if (frame == pFrame) then return end
	local frmAttachPt = HealWatch.Options.FrameAttachPoint or 'TOP'
	local ParAttachPt = HealWatch.Options.ParentAttachPoint or 'BOTTOM'
	local labelPoint1,labelPoint2,parPoint1,parPoint2
	local xOff,yOff = 3,-4
	if (frame ~= getglobal("HealWatchCastFrame")) then frame:ClearAllPoints() end
	-- 1 = up, 2 = down, 3 = right, 4 = left
	if (HealWatch.Options.LabelGrowDirection == 1) then
		labelPoint1,labelPoint2,parPoint1,parPoint2 = 'BOTTOMLEFT','BOTTOMRIGHT','TOPLEFT','TOPRIGHT'
	elseif (HealWatch.Options.LabelGrowDirection == 2) then
		labelPoint1,labelPoint2,parPoint1,parPoint2 = 'TOPLEFT','TOPRIGHT','BOTTOMLEFT','BOTTOMRIGHT'
	elseif (HealWatch.Options.LabelGrowDirection == 3) then
		labelPoint1,labelPoint2,parPoint1,parPoint2 = 'TOPLEFT','BOTTOMLEFT','TOPRIGHT','BOTTOMRIGHT'
	elseif (HealWatch.Options.LabelGrowDirection == 4) then
		labelPoint1,labelPoint2,parPoint1,parPoint2 = 'TOPRIGHT','BOTTOMRIGHT','TOPLEFT','BOTTOMLEFT'
	else
		labelPoint1,labelPoint2,parPoint1,parPoint2 = 'TOPLEFT','TOPRIGHT','BOTTOMLEFT','BOTTOMRIGHT'
	end
	if (not pFrame or pFrame == HealWatchCastFrame) then
		if (HealWatch.Options.LabelGrowDirection == 4) then
			xOff,yOff = -3,-4
		end
		parPoint1 = labelPoint1
		frame:SetPoint(labelPoint1,HealWatchCastFrame,parPoint1,xOff,yOff)
			--frame:SetPoint(labelPoint2,HealWatchCastFrame,parPoint2,-3,-4)
		return
	end
	if (frame.spark and pFrame.spark) then
		frame:SetPoint(frmAttachPt.."LEFT",pFrame,ParAttachPt.."LEFT",0,0)
		frame:SetPoint(frmAttachPt.."RIGHT",pFrame,ParAttachPt.."RIGHT",0,0)
	elseif (frame.spark and not pFrame.spark) then
		frame:SetPoint(frmAttachPt.."LEFT",pFrame,ParAttachPt.."LEFT",10,0)
		frame:SetPoint(frmAttachPt.."RIGHT",pFrame,ParAttachPt.."RIGHT",-10,0)
	elseif (not frame.spark and pFrame.spark) then
		frame:SetPoint(frmAttachPt.."LEFT",pFrame,ParAttachPt.."LEFT",-10,0)
		frame:SetPoint(frmAttachPt.."RIGHT",pFrame,ParAttachPt.."RIGHT",10,0)
	elseif (not frame.spark and not pFrame.spark) then
		frame:SetPoint(labelPoint1,pFrame,parPoint1)
		frame:SetPoint(labelPoint2,pFrame,parPoint2)
	end
end

function HealWatch.OnUpdate()
	if (not this.heal) then
		this:Hide()
		return
	end
	local heal = this.heal
	local status = GetTime()
	local spark = this.spark
	if ( status > heal.stopTime or heal.frame ~= this) then
		HealWatch.RemCastBar(this)
		return
	end
	this.bar:SetValue(status)
	local sparkPos = min(((status - heal.startTime) / (heal.stopTime - heal.startTime)) * this.width,this.width)
	this.time:SetText(string.format('%.1f',heal.stopTime - status))
	if ( sparkPos < 0 ) then sparkPos = 0 end
	this.spark:SetPoint("CENTER",this,"LEFT",sparkPos,2)
end

function HealWatch.UpdateWidths()
	local frame
	local width = HealWatch.Options.labelWidth
	local barWidth = width - 10
	local castBarWidth = width - 15
	local borderWidth = barWidth + 5
	local txtWidth = math.floor(width*.75)
	for i=1,table.getn(_labelFrames) do
		frame = _labelFrames[i]
		if (frame) then
			frame:SetWidth(width)
			frame.text:SetWidth(txtWidth)
		end
	end
	for i=1,table.getn(_barFrames) do
		frame = _barFrames[i]
		if (frame) then
			frame:SetWidth(width)
			frame.width = castBarWidth
			frame.bar:SetWidth(barWidth)
			frame.bar.border:SetWidth(borderWidth)
			frame.caster:SetWidth(txtWidth)
		end
	end
end

local _index = 0
local frame
	-- added to try to recover from bugs
function HealWatch.ResetFrames()
-- we can be slightly inefficient, this should rarely be called
	local _names = {}
	local _locked = {}
	-- loop through all the frames and grab the ones that are in use
	for _index,frame in ipairs(_barFrames) do
		if (frame.heal) then frame.heal.frame = nil end
		HealWatch.FreeCastBar(frame)
	end
	for _index,frame in ipairs(_labelFrames) do
		if (frame.inUse and frame.target) then
			table.insert(_names,frame.target)
			-- if the frame is locked, add it to our table
			if (frame.check:GetChecked()) then
				_locked[frame.target] = true
			end
			_frames[frame.target] = nil
		end
		frame.locked = false
		-- remove the label frame or just free it? hm, let's try free first
		--HealWatch.RemLabelFrame(frame)
		HealWatch.FreeLabelFrame(frame)
	end
	_pFrame = HealWatchCastFrame
	_headFrame = HealWatchCastFrame
	DEFAULT_CHAT_FRAME:AddMessage('Did all the freeing')
	for _index,name in ipairs(_names) do
		 HealWatch.AddLabelFrame(name,_locked[name])
	end
end