-- 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 = ...

MereHealingFrames.HealingPanelsLocked = false
MereHealingFrames.HealingPanelLayout = {
						TopLeftX = 400,
						TopLeftY = 650,
						BorderX = 4,
						BorderY = 4,
						PanelGapX = 2,
						PanelGapY = 2,
						PanelColumns = 4,
						PanelRows = 5,
						PanelWidth = 100,
						PanelHeight = 60,
						Name = "Unnamed Healing Panel Layout",
						LayoutOffset = 0,
						RoleFilter = nil,
						GroupingFilter = nil,
						CallingFilter = nil,
						orderBy = "compactgroup",
						AnchorPoint = "TOPLEFT",
						ShowNameLabel = true,
						LabelHeight = 20,
						PanelSettings = nil,
						FillRowsThenColumns = false,
                        FillRightToLeft = false,
                        FillBottomToTop = false,

						-- implementation details
						Height = 250,
						Width = 400,
						RelayPanelsInGroup = nil,
						Frame = nil,
						Panels = nil,
						isSecure = false,
						specifierMapping = nil,
						configuringLayout = false,
                        PendingLayoutChange = false,
						}



local SavedVariables = {
	TopLeftX = true,
	TopLeftY = true,
	BorderX = true,
	BorderY = true,
	PanelGapX = true,
	PanelGapY = true,
	PanelColumns = true,
	PanelRows = true,
	PanelWidth = true,
	PanelHeight = true,
	Name = true,
	LayoutOffset = true,
	RoleFilter = true,
	CallingFilter = true,
	GroupingFilter = true,
	orderBy = true,
	AnchorPoint = true,
	ShowNameLabel = true,
	LabelHeight = true,
	PanelSettings = true,
    FillRowsThenColumns = true,
    FillRightToLeft = true,
    FillBottomToTop = true,
	}

function MereHealingFrames.HealingPanelLayout:Save()
	local savedLayout = {}
	for key, value in pairs(SavedVariables) do
		savedLayout[key] = self[key]
	end

	return savedLayout
end


function MereHealingFrames.HealingPanelLayout:new (settings)
	local this = settings or {}

	setmetatable(this, self)
	self.__index = self

	return this
end

local groupNames = {
    [1] = "group01",
    [2] = "group02",
    [3] = "group03",
    [4] = "group04",
    [5] = "group05",

    [6] = "group06",
    [7] = "group07",
    [8] = "group08",
    [9] = "group09",
    [10] = "group10",

    [11] = "group11",
    [12] = "group12",
    [13] = "group13",
    [14] = "group14",
    [15] = "group15",

    [16] = "group16",
    [17] = "group17",
    [18] = "group18",
    [19] = "group19",
    [20] = "group20",
}


MereHealingFrames.HealingPanelSettings = {
		ManaHeight = 14,
		EnergyHeight = 14,
		ShowMana = true,
		ShowEnergy = true,

		ManaTextFormatter = "full",
		EnergyTextFormatter = "none",
		HealthTextFormatter = "full",

		ManaTextRounding = "thousandspoint",
		EnergyTextRounding = "none",
		HealthTextRounding = "thousandspoint",

		HealthTextBordered = true,
		ManaTextBordered = true,
		EnergyTextBordered = true,

		callingColouredText = true,
		borderPlayerName = true,
		callingColouredHealth = false,
        roleColouredHealth = false,

		borderSize = 2,
		buffConfiguration = nil,

        absorbShown = true,
        NameFontSize = 14,

        EnergyFontSize = nil,
        ManaFontSize = nil,
        HealthFontSize = 10,
}



function MereHealingFrames.HealingPanelSettings:new(panelSettings)
	local this = panelSettings or {}

	setmetatable(this, self)
	self.__index = self

	this.buffConfiguration = MereHealingFrames.HealingPanelBuffSettings:new(this.buffConfiguration)

    -- Convert the Heights into fontsizes for backwards compat.
    if (not this.EnergyFontSize) then
        this.EnergyFontSize = math.floor(MereHealingFrames.Config.UI.Utilities.CalcPointFromPixels(this.EnergyHeight))
    end
    if (not this.ManaFontSize) then
        this.ManaFontSize = math.floor(MereHealingFrames.Config.UI.Utilities.CalcPointFromPixels(this.ManaHeight))
    end

	return this
end

MereHealingFrames.HealingPanelBuffSettings =
{
    topRow = 5,
    topRightToLeft = true,
    middleRow = 0,
    middleRightToLeft = false,
    bottomRow = 0,
    bottomRightToLeft = false,
}

function MereHealingFrames.HealingPanelBuffSettings:new(settings)
    local this = settings or {}

    setmetatable(this, self)
    self.__index = self
    this.slots = MereHealingFrames.HealingPanelBuffSlots:new(this.slots)
    return this
end

MereHealingFrames.HealingPanelBuffSlots = {
    1,2,3,4,5,
    0,0,0,0,0,
    0,0,0,0,0,
    0,0,0,0,0,
}

function MereHealingFrames.HealingPanelBuffSlots:new(slots)
    local this = slots or {}

    setmetatable(this, self)
    self.__index = self
    return this
end

function MereHealingFrames.HealingPanelLayout.Create (settings)
	local layout = MereHealingFrames.HealingPanelLayout:new (settings)

	layout.Panels = {}
	layout.specifierMapping = {}
	layout.RoleFilter = layout.RoleFilter or { heal = true, tank = true, support = true, dps = true}
	layout.CallingFilter = layout.CallingFilter or { mage = true, cleric = true, warrior = true, rogue = true }
	layout.GroupingFilter = layout.GroupingFilter or { [1] = true, [2] = true, [3] = true, [4] = true }

	layout.PanelSettings = MereHealingFrames.HealingPanelSettings:new(layout.PanelSettings)

	layout:Initialize()

	return layout
end

function MereHealingFrames.HealingPanelLayout:Delete()
	self.Frame:SetVisible(false)

	for key, panel in pairs (self.Panels) do
		panel:GroupLeave()
		panel:SetVisible(false)
		MereHealingFrames.HealingPanelFactory.OldPanel(panel)
	end
	self.Panels = nil
end

function MereHealingFrames.HealingPanelLayout:RefreshPanelSettings()
	for key, panel in pairs (self.Panels) do
		panel:RefreshPanelSettings()
	end
end

function MereHealingFrames.HealingPanelLayout:Initialize (settings)
	self.Frame = UI.CreateFrame("Frame", "LayoutBackFrame", MereHealingFrames.context)
	self.Frame:SetSecureMode("restricted")

	MereHealingFrames.Debug(1, "Loading panel %s, AnchorPoint %s, position %d, %d", self.Name, self.AnchorPoint, self.TopLeftX, self.TopLeftY)
	self.Frame:SetPoint(self.AnchorPoint, UIParent, "TOPLEFT", self.TopLeftX, self.TopLeftY)
	self.Frame:SetBackgroundColor(MereHealingFrames.Colours.FetchRGBA("LayoutBackground"))

	self.Frame:SetLayer(MereHealingFrames.Layers.CalculateLayer(self.LayoutOffset, "LayoutBase"))

	self.NameFrame = UI.CreateFrame("Frame", "LayoutNameFrame", self.Frame )
	self.NameFrame:SetHeight(self.LabelHeight)
	self.NameFrame:SetPoint("BOTTOMLEFT", self.Frame, "TOPLEFT")
	self.NameFrame:SetPoint("BOTTOMRIGHT", self.Frame, "TOPRIGHT")
	self.NameFrame:SetBackgroundColor(MereHealingFrames.Colours.FetchRGBA("LayoutBackground"))

	self.NameLabel = UI.CreateFrame("Text", "LayoutNameLabel", self.NameFrame)
	self.NameLabel:SetPoint("CENTER", self.NameFrame, "CENTER")
	self.NameLabel:SetText(self.Name)
	self.NameLabel:SetFontSize(self.LabelHeight - 2)

	self.NameLabel:SetWidth(self.NameFrame:GetWidth())

	self:SetOrderBy(self.orderBy)

	self:Resize(self.Width, self.Height)
	self:UnlockLayout()
end

function MereHealingFrames.HealingPanelLayout:Resize(width, height)
	self.Width = width
	self.Height = height

	self:RelayPanels()
end

function MereHealingFrames.HealingPanelLayout:SetName(newName)
	self.Name = newName
	self.NameLabel:SetText(self.Name)
end

function MereHealingFrames.HealingPanelLayout:SetConfiguring(configuring)
	self.configuringLayout = configuring

	self.NameFrame:SetVisible(self.ShowNameLabel or self.configuringLayout)

	if (self.configuringLayout) then
		self.Frame:SetBackgroundColor(MereHealingFrames.Colours.FetchRGBA("LayoutBackgroundConfiguring"))
		self.NameFrame:SetBackgroundColor(MereHealingFrames.Colours.FetchRGBA("LayoutBackgroundConfiguring"))
	else
		self.Frame:SetBackgroundColor(MereHealingFrames.Colours.FetchRGBA("LayoutBackground"))
		self.NameFrame:SetBackgroundColor(MereHealingFrames.Colours.FetchRGBA("LayoutLabelBackground"))
	end
end


function MereHealingFrames.HealingPanelLayout:SetOrderBy(newOrder)
	local newLayoutFunc = MereHealingFrames.HealingPanelLayout.GroupLayouts[newOrder]
	if newLayoutFunc == nil then
		return false
	end

	self.layoutSequenceList = newLayoutFunc
	self.orderBy = newOrder
	self:RelayPanels()
	return true
end


function MereHealingFrames.HealingPanelLayout:RelayPanels()
	if self.isSecure then return end

	self.NameFrame:SetHeight(self.LabelHeight)
	self.NameLabel:SetFontSize(self.LabelHeight - 2)

	self:ApplyFilters()

	MereHealingFrames.Debug(4, "relaying %d panels", #self.Panels)

	self.NameFrame:SetVisible(self.ShowNameLabel or self.configuringLayout)

	local panel = self.specifierMapping["player"]
	if panel then
        local panelWidth = self.PanelWidth
        local panelHeight = self.PanelHeight
		-- solo layout, place player in the top left
		MereHealingFrames.Debug(4, "solo layout")
		panel:Move(self.BorderX, self.BorderY)
		panel:Resize(panelWidth, panelHeight)

		self.Frame:SetWidth(panelWidth + (2*self.BorderX))
		self.Frame:SetHeight(panelHeight + (2*self.BorderY))
	else
		self:RelayLayoutPanels()
	end

	self.NameLabel:SetWidth(self.NameFrame:GetWidth())
end

function MereHealingFrames.HealingPanelLayout:calculateCompactedGroupList()
	local fillSize
	if self.FillRowsThenColumns then
        fillSize = self.PanelColumns
	else
        fillSize = self.PanelRows
	end

	local groupList = {}
	local currentEntry = 1
    local specMapping = self.specifierMapping

    for i = 1, 20 do
        local groupName = groupNames[i]
		local panel = specMapping[groupName];

        if panel then
			groupList[currentEntry] = panel
			currentEntry = currentEntry + 1
        end

        if ((i % fillSize) == 0) then
            while currentEntry <= i do
                groupList[currentEntry] = false
                currentEntry = currentEntry + 1
            end
        end
	end

	return groupList
end

function MereHealingFrames.HealingPanelLayout:calculateGroupList()
	local groupList = {}
	local specMapping = self.specifierMapping
	for i = 1, 20 do
        local groupName = groupNames[i]
		local panel = specMapping[groupName];

		groupList[i] = panel or false
	end

	return groupList
end

function MereHealingFrames.HealingPanelLayout:calculateNamedList()
	local nameSort = {}
	for k, panel in pairs(self.Panels) do
		table.insert(nameSort, panel)
	end

	if #nameSort == 0  then
		MereHealingFrames.Debug(4, "no panels to display")
		return {}
	end

	table.sort(nameSort, function (a,b) return a.playerInfo.name < b.playerInfo.name end)

	return nameSort
end

local roleSort = {
	tank = 1,
	heal = 2,
	support = 3,
	dps = 4,
	unknown = 5,
}

function MereHealingFrames.HealingPanelLayout:calculateRoleAndNameSortedList()
	local nameSort = {}
	for k, panel in pairs(self.Panels) do
		table.insert(nameSort, panel)
	end

	if #nameSort == 0  then
		MereHealingFrames.Debug(4, "no panels to display")
		return {}
	end

	table.sort(nameSort, function (a,b)
							local roleA, roleB = roleSort[a.playerInfo.role], roleSort[b.playerInfo.role]
							if roleA < roleB then
								return true
							elseif roleA == roleB then
								return a.playerInfo.name < b.playerInfo.name
							else
								return false
							end
							end)

	return nameSort
end

function MereHealingFrames.HealingPanelLayout:RowCounter()
    --if self.FillBottomToTop then
    --    return self.PanelRows, 1, -1
    --else
        return 1, self.PanelRows, 1
    --end
end

function MereHealingFrames.HealingPanelLayout:ColumnCounter()
    --if self.FillRightToLeft then
    --    return self.PanelColumns, 1, -1
    --else
        return 1, self.PanelColumns, 1
    --end
end

function MereHealingFrames.HealingPanelLayout:LayoutAnchorPoint()
    local upDown, leftRight
    if self.FillBottomToTop then
        upDown = "BOTTOM"
    else
        upDown = "TOP"
    end
    if self.FillRightToLeft then
        leftRight = "RIGHT"
    else
        leftRight = "LEFT"
    end
    return upDown..leftRight
end

function MereHealingFrames.HealingPanelLayout:PositionPanel(column, row, panel, anchorPoint)
    if panel then
        local panelWidth, panelHeight = self.PanelWidth, self.PanelHeight
        local borderWidth, borderHeight = self.BorderX, self.BorderY

        local origPanelX = ( (panelWidth + self.PanelGapX) * (column - 1)) + borderWidth
        local origPanelY = ( (panelHeight + self.PanelGapY) * (row - 1)) + borderHeight
        local panelX, panelY
        if self.FillRightToLeft then
            panelX = -origPanelX - panelWidth
        else
            panelX = origPanelX
        end
        if self.FillBottomToTop then
            panelY = -origPanelY - panelHeight
        else
            panelY = origPanelY
        end

        panel:Move(panelX, panelY, anchorPoint)
        panel:Resize(panelWidth, panelHeight)

        return origPanelX + panelWidth + borderWidth, origPanelY + panelHeight + borderHeight
    end
    return 0, 0
end

function MereHealingFrames.HealingPanelLayout:RelayLayoutPanels()
	local i = 1
	local neededWidth, neededHeight = 0, 0
    local anchorPoint = self:LayoutAnchorPoint()

	local groupList = self:layoutSequenceList()

    local mincol, maxcol, inccol =  self:ColumnCounter()
    local minrow, maxrow, incrow =  self:RowCounter()

    if self.FillRowsThenColumns then
        for row = minrow, maxrow, incrow do
            for column = mincol, maxcol, inccol do
                if (i > 20) then
                    break
                end

                local bottomRightX, bottomRightY = self:PositionPanel(column, row, groupList[i], anchorPoint)
                neededWidth, neededHeight = math.max(bottomRightX, neededWidth), math.max(bottomRightY, neededHeight)
                i = i + 1
            end
        end
    else
        for column = mincol, maxcol, inccol do
            for row = minrow, maxrow, incrow do
                if (i > 20) then
                    break
                end

                local bottomRightX, bottomRightY = self:PositionPanel(column, row, groupList[i], anchorPoint)
                neededWidth, neededHeight = math.max(bottomRightX, neededWidth), math.max(bottomRightY, neededHeight)
                i = i + 1
            end
        end
    end

	-- update the background frame to the right size
	self.Frame:SetWidth(neededWidth)
	self.Frame:SetHeight(neededHeight)
end

MereHealingFrames.HealingPanelLayout.GroupLayouts = {
	group = MereHealingFrames.HealingPanelLayout.calculateGroupList,
	name = MereHealingFrames.HealingPanelLayout.calculateNamedList,
	compactgroup = MereHealingFrames.HealingPanelLayout.calculateCompactedGroupList,
	roleandname = MereHealingFrames.HealingPanelLayout.calculateRoleAndNameSortedList,
	}

function MereHealingFrames.HealingPanelLayout:SetVisible(visible)
	self.Frame:SetVisible(visible)
	self:RelayPanels()
	for k, panel in pairs(self.Panels) do
		panel:SetVisible(visible)
	end
end

function MereHealingFrames.HealingPanelLayout:UpdateSpells()
	for k, panel in pairs(self.Panels) do
		panel:UpdateSpells()
	end
end

function MereHealingFrames.HealingPanelLayout:QueueLayoutChange()
    self.PendingLayoutChange = true
end

function MereHealingFrames.HealingPanelLayout:ProcessPendingLayoutChanges()
    if self.isSecure then
        return
    end

    if self.PendingLayoutChange then
        self:SetVisible(self.Frame:GetVisible())
        self.PendingLayoutChange = false
    end
end

function MereHealingFrames.HealingPanelLayout:GroupJoin(playerInfo, silent)
	silent = silent or false

	if self.isSecure then
		table.insert(MereHealingFrames.PostSecureCallbacks, function () self:GroupJoin(playerInfo) end)
		return
	end

	local unitId = playerInfo.unitId
	local groupSpecifier = playerInfo.specifier

	MereHealingFrames.Debug(4, "group join, UnitId: %s, specifier: %s, name: %s",
		unitId, playerInfo.specifier, playerInfo.name)

	if self.Panels[unitId] then
		MereHealingFrames.Debug(1, "Recursive join blocked for unitId: %s", unitId)
		return
	end

	local panelSettings = {
		}
	local panel = MereHealingFrames.HealingPanelFactory.NewPanel(self)
	self.Panels[unitId] = panel
	self.specifierMapping[groupSpecifier] = panel

	panel:Initialize(panelSettings, self, self.LayoutOffset)
	panel:SetPlayerInfo(playerInfo)

	MereHealingFrames.Debug(4, "making layout visible, panel for unitId: %s", unitId)
	if not silent then
		self:QueueLayoutChange()
	end
end

function MereHealingFrames.HealingPanelLayout:GroupLeave(unitId, groupSpecifier, silent)
	MereHealingFrames.Debug(3, "GroupLeave, unitId %s, specifier %s", (unitId or "noID?"), groupSpecifier or "no specifier?")
	local panel = self.Panels[unitId]

	if not panel then
		return
	end

	if self.isSecure then
		table.insert(MereHealingFrames.PostSecureCallbacks, function () self:GroupLeave(unitId, groupSpecifier) end)
		if (unitId ~= MereHealingFrames.PlayerId) then
			panel:GroupLeave()
		end
		return
	end

	self.Panels[unitId] = nil

	if not groupSpecifier then
	-- hunt for this entry
		for k, v in pairs(self.specifierMapping) do
			if v == panel then
				groupSpecifier = k
				break
			end
		end
		MereHealingFrames.Debug(3, "GroupLeave, unitId %s, found specifier %s", (unitId or "noID?"), groupSpecifier or "not found")
	end

	if (groupSpecifier) then
		self.specifierMapping[groupSpecifier] = nil
	end

	panel:SetVisible(false)

	MereHealingFrames.HealingPanelFactory.OldPanel(panel)

	silent = silent or false
	if not silent then
        self:QueueLayoutChange()
	end
end

function MereHealingFrames.HealingPanelLayout:GroupChange(unitId, originalSpecifier, newSpecifier)
	local panel = self.Panels[unitId]

	if not panel then
		return
	end

	if self.isSecure then
		table.insert(MereHealingFrames.PostSecureCallbacks, function () self:GroupChange(unitId, originalSpecifier, newSpecifier) end)
		return
	end

	local overwrittenPanel = self.specifierMapping[newSpecifier]
	if (overwrittenPanel) then
		-- the new location is in use, so we're just a little out of sequence, libsrm should remove the left unit
		MereHealingFrames.Debug(5, "GroupChange, will be overwritting another group member: %s", overwrittenPanel.playerInfo.name)
	end

	local panel = self.Panels[unitId]

	MereHealingFrames.Debug(5, "GroupChange, moving %s from %s to %s",  panel.playerInfo.name, originalSpecifier, newSpecifier)

    -- only remove from the old specifier if that's actually where the player was
    if self.specifierMapping[originalSpecifier] == panel then
        self.specifierMapping[originalSpecifier] = nil
    end

	-- move the panel to the new specifier
	self.specifierMapping[newSpecifier] = panel

	-- trigger a relay
    self:QueueLayoutChange()
end

function MereHealingFrames.HealingPanelLayout:SecureEnter()
	self:LockLayout()
	self.isSecure = true
end

function MereHealingFrames.HealingPanelLayout:SecureLeave()
	self.isSecure = false
	self:UnlockLayout()
end

local ValidFilters = {
	heal = true,
	dps = true,
	tank = true,
	support = true
	}
function MereHealingFrames.HealingPanelLayout:SetRoleFilter(filter)
	local newfilter = {}
	for i, value in ipairs(filter) do
		if not ValidFilters[value] then
			return false
		end
		newfilter[value] = true
	end

	self.RoleFilter = newfilter
	self:RelayPanels()
	return true
end

local ValidCallingFilters = {
	mage = true,
	cleric = true,
	warrior = true,
	rogue = true
	}

local ValidGroupingFilters = {
	[1] = true,
	[2] = true,
	[3] = true,
	[4] = true
}

function MereHealingFrames.HealingPanelLayout:SetCallingFilter(filter)

	for key, value in pairs(filter) do
		if not ValidCallingFilters[key] then
			return false
		end
	end

	self.CallingFilter = filter
	self:RelayPanels()
	return true
end

function MereHealingFrames.HealingPanelLayout:SetGroupingFilter(filter)

	for key, value in pairs(filter) do
		if not ValidGroupingFilters[key] then
			return false
		end
	end

	self.GroupingFilter = filter
	self:RelayPanels()
	return true
end



function MereHealingFrames.HealingPanelLayout:ApplyFilters()
    local raidManagement = MereHealingFrames.RaidManagement
	local filterList = raidManagement.CreateUnitFilterList()

	-- accept unknown initially
	if self.RoleFilter then
		self.RoleFilter["unknown"] = true
	end

	if self.CallingFilter then
		self.CallingFilter["unknown"] = true
	end

    local roleFiler, callingFilter, groupingFilter = self.RoleFilter, self.CallingFilter, self.GroupingFilter

	local filterFunc = function(playerInfo)
		return roleFiler[playerInfo.role] and callingFilter[playerInfo.calling] and groupingFilter[playerInfo.grouping]
		end

	filterList = raidManagement.FilterUnitListByFunc(filterList, filterFunc)

	if self.RoleFilter then
		self.RoleFilter["unknown"] = nil
	end

	if self.CallingFilter then
		self.CallingFilter["unknown"] = nil
	end

	local units = raidManagement.Units
	local panels = self.Panels
	for unitId, displayed in pairs(filterList) do
		local panel = panels[unitId]

		if displayed and panel ~= nil
		then
			MereHealingFrames.Debug(4, "unitId %s is already displayed", unitId)
		elseif displayed then
			-- push a new panel creation through
			local playerInfo = units[unitId]
			self:GroupJoin(playerInfo, true)
		else
			-- delete a panel
			self:GroupLeave(unitId, nil, true)
		end
	end
end

function MereHealingFrames.HealingPanelLayout:UnlockLayout()
	if (MereHealingFrames.HealingPanelsLocked) then
		self:LockLayout()
		return
	end
	self.DragInfo = { dragging = false }
	self.Frame.Event.LeftDown = function (...) MereHealingFrames.HealingPanelLayout.LeftDown(self, ...) end
	self.Frame.Event.MouseMove = function (...) MereHealingFrames.HealingPanelLayout.MouseMove(self, ...) end
	self.Frame.Event.LeftUp = function (...) MereHealingFrames.HealingPanelLayout.LeftUp(self, ...) end
	self.Frame:SetMouseMasking("limited")
	self.Frame:SetBackgroundColor(MereHealingFrames.Colours.FetchRGBA("LayoutBackground"))

	self:LinkLabelFrameEvents()
end

function MereHealingFrames.HealingPanelLayout:LockLayout()
	self.DragInfo = nil
	self.Frame.Event.LeftDown = nil
	self.Frame.Event.MouseMove = nil
	self.Frame.Event.LeftUp = nil
	self.Frame:SetMouseMasking("limited")
	self:LinkLabelFrameEvents()
	self.Frame:SetBackgroundColor(MereHealingFrames.Colours.FetchRGBA("LayoutBackground"))
end

function MereHealingFrames.HealingPanelLayout:LinkLabelFrameEvents()
	self.NameFrame.Event.LeftDown = self.Frame.Event.LeftDown
	self.NameFrame.Event.MouseMove = self.Frame.Event.MouseMove
	self.NameFrame.Event.LeftUp = self.Frame.Event.LeftUp
end

function MereHealingFrames.HealingPanelLayout:LeftDown(...)
	if self.DragInfo then
		self.DragInfo.dragging = true
		self.DragInfo.offsetX = Inspect.Mouse().x - self.TopLeftX
		self.DragInfo.offsetY = Inspect.Mouse().y - self.TopLeftY
        self.DragInfo.LastX = self.TopLeftX
        self.DragInfo.LastY = self.TopLeftY
	end
end

function MereHealingFrames.HealingPanelLayout:MouseMove(event, x, y)
	if (self.DragInfo and self.DragInfo.dragging) then
		local newX = x - self.DragInfo.offsetX
		local newY = y - self.DragInfo.offsetY
        self.DragInfo.LastX = newX
        self.DragInfo.LastY = newY

		self.Frame:SetPoint(self.AnchorPoint, UIParent, "TOPLEFT", newX, newY)
	end
end

function MereHealingFrames.HealingPanelLayout:LeftUp(...)
	if self.DragInfo then
		self.DragInfo.dragging = false
		self.TopLeftX = self.DragInfo.LastX
		self.TopLeftY = self.DragInfo.LastY
	end
end


-- anchor is two part
-- horizontal is TOP, CENTER, BOTTOM
-- vertical is LEFT, CENTER, RIGHT
-- Note I did wonder about taking the standard names, but realised that they'd all be internal till here
function MereHealingFrames.HealingPanelLayout:ChangeAnchorPoint(horizontalAnchor, verticalAnchor)

    local left, top, right, bottom = self.Frame:GetBounds()
    local newX, newY
    if (horizontalAnchor == "TOP") then
        newY = top
    elseif (horizontalAnchor == "CENTER") then
        newY = top + ((bottom - top) / 2)
    elseif (horizontalAnchor == "BOTTOM") then
        newY = bottom
    else
    -- invalid param!
        return
    end

    if (verticalAnchor == "LEFT") then
        newX = left
    elseif(verticalAnchor == "CENTER") then
        newX = left + ((right-left) / 2)
    elseif(verticalAnchor == "RIGHT") then
        newX = right
    else
        return
    end

    local newAnchorPoint = horizontalAnchor .. verticalAnchor
    if (newAnchorPoint == "CENTERCENTER" ) then
        newAnchorPoint = "CENTER"
    end

    MereHealingFrames.Debug(2, "Layout Anchor point changed from %s to %s, from %d,%d to %d,%d",
        self.AnchorPoint, newAnchorPoint, self.TopLeftX, self.TopLeftY, newX, newY)

    self.Frame:ClearPoint(self.AnchorPoint)

    self.TopLeftX = newX
    self.TopLeftY = newY
    self.AnchorPoint = newAnchorPoint

    self.Frame:SetPoint(self.AnchorPoint, UIParent, "TOPLEFT", self.TopLeftX, self.TopLeftY)
end