-- 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.Config = MereHealingFrames.Config or {}
MereHealingFrames.Config.UI = MereHealingFrames.Config.UI or {}
MereHealingFrames.Config.UI.Layouts = {}


local layoutMappings = {
	{ layoutName = "BorderX", 	displayName = "Border Width", 	minimum = 1, maximum = 10 },
	{ layoutName = "BorderY", 	displayName = "Border Height", 	minimum = 1, maximum = 10 },
	{ layoutName = "PanelGapX", displayName = "Vertical Spacing", 	minimum = 1, maximum = 10 },
	{ layoutName = "PanelGapY", displayName = "Horizontal Spacing", minimum = 1, maximum = 10 },
	{ layoutName = "PanelRows", displayName = "Rows", 		minimum = 1, maximum = 20 },
	{ layoutName = "PanelColumns", displayName = "Columns", minimum = 1, maximum = 20 },
	{ layoutName = "PanelWidth", displayName = "Panel Width", 	minimum = 1, maximum = 200 },
	{ layoutName = "PanelHeight", displayName = "Panel Height", minimum = 1, maximum = 200 },
	{ layoutName = "LabelHeight", displayName = "Label Height", minimum = 5, maximum = 30 },
}

local layoutMappingToUI = {
	layoutName = nil,
	label = nil,
	slider = nil,
	frame = nil,
	}

function layoutMappingToUI:new()
	local this = {}
	this.initialized = false

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

function layoutMappingToUI:CreateUI(layoutName, labelName, minimum, maximum, parentFrame)
	self.layoutName = layoutName
	self.frame = UI.CreateFrame("Frame", "Frame"..layoutName, parentFrame)
	self.label = UI.CreateFrame("Text", "Label"..layoutName, self.frame)
	self.slider = UI.CreateFrame("SimpleSlider", "Slider"..layoutName, self.frame)

	self.label:SetText(labelName)
	self.slider:SetRange(minimum, maximum)

	self.label:SetPoint("LEFT", self.frame, "LEFT")
	self.label:SetWidth(100)

	self.slider:SetPoint("TOPLEFT", self.frame, "TOPLEFT", 120, 0)
	self.label:SetPoint("CENTERY", self.slider, "CENTERY")

	self.frame:SetHeight(self.slider:GetHeight())
	self.frame:SetWidth(self.slider:GetRight())
end

function layoutMappingToUI:GetContent()
	return self.frame
end


function layoutMappingToUI:SetCurrentValue(value)
	self.slider:SetPosition(value, true)
end

function layoutMappingToUI:GetCurrentValue()
	return self.slider:GetPosition()
end

function layoutMappingToUI:SetCallback(callbackFunction)
	self.slider.Event.SliderChange = function ()
		callbackFunction(self.layoutName, self:GetCurrentValue())
		end
end


local checkboxWrapper = {
	layoutName = nil,
	checkbox = nil,
	}

function checkboxWrapper:new()
	local this = {}
	this.initialized = false

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

function checkboxWrapper:CreateUI(layoutName, labelName, parentFrame)
	self.layoutName = layoutName

	self.checkbox = UI.CreateFrame("SimpleCheckbox", "SimpleCheckbox"..layoutName, parentFrame)
	self.checkbox:SetText(labelName)
end

function checkboxWrapper:GetContent()
	return self.checkbox
end


function checkboxWrapper:SetCurrentValue(value)
	local tmp = self.checkbox.Event.CheckboxChange
	self.checkbox.Event.CheckboxChange = nil

	-- not sure silent is working?
	self.checkbox:SetChecked(value, true)

	self.checkbox.Event.CheckboxChange = tmp
end

function checkboxWrapper:GetCurrentValue()
	return self.checkbox:GetChecked()
end

function checkboxWrapper:SetCallback(callbackFunction)
	self.checkbox.Event.CheckboxChange = function ()
		callbackFunction(self.layoutName, self:GetCurrentValue())
	end
end


function MereHealingFrames.Config.UI.Layouts:new ()
	local this = {}
	this.initialized = false

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

function MereHealingFrames.Config.UI.Layouts:CreateUI (configWindow, tabs)
	self.Frame = UI.CreateFrame("Frame", "LayoutConfigFrame", configWindow)

	tabs:AddTab("Layouts", self.Frame)

	local LayoutsFrame = {
		getSetList = MereHealingFrames.Config.UI.Layouts.GetLayouts,	-- table <- nil
		renameSet = MereHealingFrames.Config.UI.Layouts.RenameLayout,	-- nil <- currentName, newName
		addSet = MereHealingFrames.Config.UI.Layouts.AddNewLayout,		-- nil <- setName
		deleteSet = MereHealingFrames.Config.UI.Layouts.DeleteLayout,	-- nil <- setName
		setSelected = function(...)  MereHealingFrames.Config.UI.Layouts.ChangeLayoutSelection(self, ...) end,	-- nil <- setName
		addButtonText = "Add Layout",
		deleteButtonText = "Delete Layout",
		renameButtonText = "Rename Layout",
	}
	self.LayoutSets = MereHealingFrames.Config.UI.SetsFrame:new (LayoutsFrame, self:GetContent())
	self.LayoutSets:CreateUI(self:GetContent())
	self.LayoutSets:GetContent():SetPoint("TOPLEFT", self:GetContent(), "TOPLEFT")
	self.LayoutSets:GetContent():SetPoint("BOTTOMLEFT", self:GetContent(), "BOTTOMLEFT")

	self.layoutValues = {}

	self.LayoutTabs = UI.CreateFrame("SimpleTabView", "Config_Tabs", self:GetContent())
	self.LayoutTabs:SetBackgroundColor(0,0,0,0.5)
	self.LayoutTabs:SetPoint("TOPLEFT", self.LayoutSets:GetContent(), "TOPRIGHT", 5, 0)
	self.LayoutTabs:SetPoint("BOTTOMRIGHT", self:GetContent(), "BOTTOMRIGHT")

	self.LayoutTabs:AddTab("Sizing", self:CreateSizingTab())
	self.LayoutTabs:AddTab("Filtering and Misc", self:CreateFilteringTab())
	self.LayoutTabs:AddTab("Panel Settings", self:CreatePanelSettingsTab())
	self:CreateBuffSettingsTab(self.LayoutTabs)
	self.LayoutTabs:AddTab("Soul Specs", self:CreateSpecsTab())

	self.LayoutSets:SetSelectedIndex(1)
end

function MereHealingFrames.Config.UI.Layouts.GetLayouts()
	local items = {}
	for key, layout in pairs(MereHealingFrames.Layouts) do
		if layout then
			table.insert(items, key)
		end
	end
	return items
end

function MereHealingFrames.Config.UI.Layouts.AddNewLayout(newSetName)
	while MereHealingFrames.Layouts[newSetName] do
		newSetName = "New Layout ".. Inspect.Time.Frame()
	end

	local layoutSettings = {
		Name = newSetName,
	}
	local layout =  MereHealingFrames.HealingPanelLayout.Create(layoutSettings)
	MereHealingFrames.Layouts[newSetName] = layout
	MereHealingFrames.RaidManagement.PopulateLayout(layout)
	layout:UpdateSpells()
	layout:SetVisible(true)
end

function MereHealingFrames.Config.UI.Layouts.DeleteLayout(setName)
	local layout = MereHealingFrames.Layouts[setName]

	if not layout then
		return
	end

	MereHealingFrames.Layouts[setName] = nil
	layout:Delete()
end

function MereHealingFrames.Config.UI.Layouts.RenameLayout(currentSetName, newSetName)
	local layout = MereHealingFrames.Layouts[currentSetName]

	if MereHealingFrames.Layouts[newSetName] then
		print("Unable to rename layout, a layout with that name already exists")
		return
	end

	if not layout then
		return
	end

	MereHealingFrames.Layouts[currentSetName] = nil
	layout:SetName(newSetName)
	MereHealingFrames.Layouts[newSetName] = layout
end


local AnchorPoints = {
    "TOPLEFT",
    "TOPCENTER",
    "TOPRIGHT",
    "CENTERLEFT",
    "CENTER",
    "CENTERRIGHT",
    "BOTTOMLEFT",
    "BOTTOMCENTER",
    "BOTTOMRIGHT"
}

local AnchorPointsInternal = {
    {"TOP", "LEFT"},
    {"TOP", "CENTER"},
    {"TOP", "RIGHT"},
    {"CENTER", "LEFT"},
    {"CENTER", "CENTER"},
    {"CENTER", "RIGHT"},
    {"BOTTOM", "LEFT"},
    {"BOTTOM", "CENTER"},
    {"BOTTOM", "RIGHT"},
}

local function anchorPointToolTipText(tooltip)
    return "The Anchor Point is the point on the layout that is fixed to the screen, as it grows it grows from this point"
end

function MereHealingFrames.Config.UI.Layouts:CreateSizingTab()
	local topOffsetY = 5
	self.sizing = {}
	self.sizing.Frame = UI.CreateFrame("Frame", "LayoutSizingTab", self:GetContent())
	for index, config in ipairs(layoutMappings) do
		self.layoutValues[config.layoutName] = layoutMappingToUI:new()
		self.layoutValues[config.layoutName]:CreateUI(config.layoutName, config.displayName, config.minimum, config.maximum, self.sizing.Frame)
		self.layoutValues[config.layoutName]:GetContent():SetPoint("TOPLEFT", self.sizing.Frame, "TOPLEFT", 5, topOffsetY)

		self.layoutValues[config.layoutName]:SetCallback(function (...) MereHealingFrames.Config.UI.Layouts.ChangeValue(self, ...) end)

		topOffsetY = topOffsetY + 25
    end

    self.sizing.anchorLabel = UI.CreateFrame("Text", "anchorLabel", self.sizing.Frame)
    self.sizing.anchorLabel:SetText("Anchor Point")
    self.sizing.anchorLabel:SetPoint("TOPLEFT", self.sizing.Frame, "TOPLEFT", 5, topOffsetY)

    self.sizing.anchorDropDown = UI.CreateFrame("SimpleSelect", "energyFormattingDropdown", self.sizing.Frame)
    self.sizing.anchorDropDown:SetItems(AnchorPoints, AnchorPointsInternal)
    self.sizing.anchorDropDown:SetPoint("TOPLEFT", self.sizing.Frame, "TOPLEFT", 130, topOffsetY)
    self.sizing.anchorDropDown:SetBorder(1, 1, 1, 1, 1)
    self.sizing.anchorDropDown:ResizeToFit()

    self.sizing.anchorDropDown.Event.ItemSelect = function (item, value, index) MereHealingFrames.Config.UI.Layouts.ChangeAnchorPoint(self, index[1], index[2]) end

    MereHealingFrames.Config.ToolTipControl:InjectEvents(self.sizing.anchorLabel, anchorPointToolTipText)

    return self.sizing.Frame
end

local FormattingTypesInternal = {
	"none",
	"percentage",
	"currentMax",
	"full",
	"missing",
	}

local FormattingTypes = {
	"no text",
	"percentage",
	"current/max",
	"current/max (percentage)",
	"missing health (no text for full health)",
	}

local RoundingTypesInternal = {
	"none",
	"thousandspoint",
	"thousands",
	}

local RoundingTypes = {
	"no rounding",
	"rounded to nearest 100",
	"rounded to nearest 1,000",
	}

function MereHealingFrames.Config.UI.Layouts:CreatePanelSettingsTab()
	local topOffsetY = 5
	self.panelSettings = {}
	local panelSettings = self.panelSettings
	panelSettings.tabFrame = UI.CreateFrame("Frame", "LayoutPanelSettingsTab", self:GetContent())

    panelSettings.panelSettingsScrollView = UI.CreateFrame("SimpleScrollView", "BuffSlotScroller", panelSettings.tabFrame)
    panelSettings.Frame = UI.CreateFrame("Frame", "BuffSlotList", panelSettings.panelSettingsScrollView)

	-- wonder if this can all be wrapped up somehow, but for now

	panelSettings.HealthBarLabel = UI.CreateFrame("Text", "HealthBarLabel", panelSettings.Frame)
	panelSettings.HealthBarLabel:SetText("Health Bar Configuration")
	panelSettings.HealthBarLabel:SetPoint("TOPLEFT", panelSettings.Frame, "TOPLEFT", 5, 5)

	local indentX = 30
	local previousFrame = panelSettings.HealthBarLabel

	panelSettings.healthFormattinglabel = UI.CreateFrame("Text", "healthFormattinglabel", panelSettings.Frame)
	panelSettings.healthFormattinglabel:SetText("Number Formatting:")
	panelSettings.healthFormattinglabel:SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 0)

	panelSettings.healthFormattingDropdown = UI.CreateFrame("SimpleSelect", "healthFormattingDropdown", panelSettings.Frame)
	panelSettings.healthFormattingDropdown:SetItems( FormattingTypes, FormattingTypesInternal )
	panelSettings.healthFormattingDropdown:SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", 150 + indentX, 0)
	panelSettings.healthFormattingDropdown:SetBorder(1, 1, 1, 1, 1)
	panelSettings.healthFormattingDropdown:ResizeToFit()
	panelSettings.healthFormattingDropdown:SetLayer(10)

	indentX = 0
	previousFrame = panelSettings.healthFormattinglabel

	panelSettings.healthRoundinglabel = UI.CreateFrame("Text", "healthRoundinglabel", panelSettings.Frame)
	panelSettings.healthRoundinglabel:SetText("Number Rounding:")
	panelSettings.healthRoundinglabel:SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 5)

	panelSettings.healthRoundingDropdown = UI.CreateFrame("SimpleSelect", "healthRoundingDropdown", panelSettings.Frame)
	panelSettings.healthRoundingDropdown:SetItems( RoundingTypes, RoundingTypesInternal  )
	panelSettings.healthRoundingDropdown:SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", 150, 5)
	panelSettings.healthRoundingDropdown:SetBorder(1, 1, 1, 1, 1)
	panelSettings.healthRoundingDropdown:ResizeToFit()
	panelSettings.healthRoundingDropdown:SetLayer(9)

	previousFrame = panelSettings.healthRoundinglabel

	panelSettings.callingColouredHealth = checkboxWrapper:new()
	panelSettings.callingColouredHealth:CreateUI("callingColouredHealth", "Health Bar is calling coloured:", panelSettings.Frame)
	panelSettings.callingColouredHealth:GetContent():SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 5)
	panelSettings.callingColouredHealth:GetContent():SetLabelPos("left")

	previousFrame = panelSettings.callingColouredHealth:GetContent()

    panelSettings.roleColouredHealth = checkboxWrapper:new()
    panelSettings.roleColouredHealth:CreateUI("callingColouredHealth", "Health Bar is role coloured:", panelSettings.Frame)
    panelSettings.roleColouredHealth:GetContent():SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 5)
    panelSettings.roleColouredHealth:GetContent():SetLabelPos("left")

    previousFrame = panelSettings.roleColouredHealth:GetContent()

	panelSettings.HealthTextBordered = checkboxWrapper:new()
	panelSettings.HealthTextBordered:CreateUI("HealthTextBordered", "Health Text is bordered:", panelSettings.Frame)
	panelSettings.HealthTextBordered:GetContent():SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 5)
	panelSettings.HealthTextBordered:GetContent():SetLabelPos("left")

	previousFrame = panelSettings.HealthTextBordered:GetContent()

    panelSettings.healthFontSize = layoutMappingToUI:new()
    panelSettings.healthFontSize:CreateUI("", "Health Font Size:", 1, 30, panelSettings.Frame)
    panelSettings.healthFontSize:GetContent():SetPoint("TOPLEFT",  previousFrame, "BOTTOMLEFT", 0, 5)

    previousFrame = panelSettings.healthFontSize:GetContent()

	panelSettings.manaRuler = MereHealingFrames.Config.UI.Utilities.CreateRuler(panelSettings.Frame)
	panelSettings.manaRuler:SetPoint("TOP", previousFrame, "BOTTOM", nil, 5)

	panelSettings.ManaBarLabel = UI.CreateFrame("Text", "ManaBarLabel", panelSettings.Frame)
	panelSettings.ManaBarLabel:SetText("Mana Bar Configuration")
	panelSettings.ManaBarLabel:SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", -30, 7)

	previousFrame = panelSettings.ManaBarLabel
	indentX = 30

	panelSettings.manaCheckBox = checkboxWrapper:new()
	panelSettings.manaCheckBox:CreateUI("manaCheckBox", "Display mana bars:", panelSettings.Frame)
	panelSettings.manaCheckBox:GetContent():SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 0)
	panelSettings.manaCheckBox:GetContent():SetLabelPos("left")

	indentX = 0

	previousFrame = panelSettings.manaCheckBox:GetContent()

	panelSettings.manaFormattinglabel = UI.CreateFrame("Text", "healthFormattinglabel", panelSettings.Frame)
	panelSettings.manaFormattinglabel:SetText("Number Formatting:")
	panelSettings.manaFormattinglabel:SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 0)

	panelSettings.manaFormattingDropdown = UI.CreateFrame("SimpleSelect", "manaFormattingDropdown", panelSettings.Frame)
	panelSettings.manaFormattingDropdown:SetItems( FormattingTypes, FormattingTypesInternal )
	panelSettings.manaFormattingDropdown:SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", 150 + indentX, 0)
	panelSettings.manaFormattingDropdown:SetBorder(1, 1, 1, 1, 1)
	panelSettings.manaFormattingDropdown:ResizeToFit()
	panelSettings.manaFormattingDropdown:SetLayer(8)

	previousFrame = panelSettings.manaFormattinglabel

	panelSettings.manaRoundinglabel = UI.CreateFrame("Text", "manaRoundinglabel", panelSettings.Frame)
	panelSettings.manaRoundinglabel:SetText("Number Rounding:")
	panelSettings.manaRoundinglabel:SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 5)

	panelSettings.manaRoundingDropdown = UI.CreateFrame("SimpleSelect", "manaRoundingDropdown", panelSettings.Frame)
	panelSettings.manaRoundingDropdown:SetItems( RoundingTypes, RoundingTypesInternal )
	panelSettings.manaRoundingDropdown:SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", 150, 5)
	panelSettings.manaRoundingDropdown:SetBorder(1, 1, 1, 1, 1)
	panelSettings.manaRoundingDropdown:ResizeToFit()
	panelSettings.manaRoundingDropdown:SetLayer(7)

	previousFrame = panelSettings.manaRoundinglabel

	panelSettings.manaHeight = layoutMappingToUI:new()
	panelSettings.manaHeight:CreateUI("", "Mana bar height:", 1, 30, panelSettings.Frame)
	panelSettings.manaHeight:GetContent():SetPoint("TOPLEFT",  previousFrame, "BOTTOMLEFT", 0, 5)

	previousFrame = panelSettings.manaHeight:GetContent()

    panelSettings.manaFontSize = layoutMappingToUI:new()
    panelSettings.manaFontSize:CreateUI("", "Mana Font Size:", 1, 30, panelSettings.Frame)
    panelSettings.manaFontSize:GetContent():SetPoint("TOPLEFT",  previousFrame, "BOTTOMLEFT", 0, 5)

    previousFrame = panelSettings.manaFontSize:GetContent()

	panelSettings.ManaTextBordered = checkboxWrapper:new()
	panelSettings.ManaTextBordered:CreateUI("ManaTextBordered", "Mana Text is bordered:", panelSettings.Frame)
	panelSettings.ManaTextBordered:GetContent():SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 2)
	panelSettings.ManaTextBordered:GetContent():SetLabelPos("left")

	previousFrame = panelSettings.ManaTextBordered:GetContent()

	panelSettings.energyRuler = MereHealingFrames.Config.UI.Utilities.CreateRuler(panelSettings.Frame)
    panelSettings.energyRuler:SetPoint("TOP", previousFrame, "BOTTOM", nil, 5)

	panelSettings.EnergyBarLabel = UI.CreateFrame("Text", "EnergyBarLabel", panelSettings.Frame)
	panelSettings.EnergyBarLabel:SetText("Energy Bar configuration")
	panelSettings.EnergyBarLabel:SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", -30, 10)

	previousFrame = panelSettings.EnergyBarLabel
	indentX = 30

	panelSettings.energyCheckBox = checkboxWrapper:new()
	panelSettings.energyCheckBox:CreateUI("energyCheckBox", "Display energy bars:", panelSettings.Frame)
	panelSettings.energyCheckBox:GetContent():SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 0)
	panelSettings.energyCheckBox:GetContent():SetLabelPos("left")
	indentX = 0

	previousFrame = panelSettings.energyCheckBox:GetContent()

	panelSettings.energyFormattinglabel = UI.CreateFrame("Text", "energyFormattinglabel", panelSettings.Frame)
	panelSettings.energyFormattinglabel:SetText("Number Formatting:")
	panelSettings.energyFormattinglabel:SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 0)

	panelSettings.energyFormattingDropdown = UI.CreateFrame("SimpleSelect", "energyFormattingDropdown", panelSettings.Frame)
	panelSettings.energyFormattingDropdown:SetItems( FormattingTypes, FormattingTypesInternal )
	panelSettings.energyFormattingDropdown:SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", 150 + indentX, 0)
	panelSettings.energyFormattingDropdown:SetBorder(1, 1, 1, 1, 1)
	panelSettings.energyFormattingDropdown:ResizeToFit()
	panelSettings.energyFormattingDropdown:SetLayer(6)

	indentX = 0
	previousFrame = panelSettings.energyFormattinglabel

	panelSettings.energyRoundinglabel = UI.CreateFrame("Text", "energyRoundinglabel", panelSettings.Frame)
	panelSettings.energyRoundinglabel:SetText("Number Rounding:")
	panelSettings.energyRoundinglabel:SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 5)

	panelSettings.energyRoundingDropdown = UI.CreateFrame("SimpleSelect", "energyRoundingDropdown", panelSettings.Frame)
	panelSettings.energyRoundingDropdown:SetItems( RoundingTypes, RoundingTypesInternal )
	panelSettings.energyRoundingDropdown:SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", 150, 5)
	panelSettings.energyRoundingDropdown:SetBorder(1, 1, 1, 1, 1)
	panelSettings.energyRoundingDropdown:ResizeToFit()
	panelSettings.energyRoundingDropdown:SetLayer(5)

	previousFrame = panelSettings.energyRoundinglabel

	panelSettings.energyHeight = layoutMappingToUI:new()
	panelSettings.energyHeight:CreateUI("", "Energy bar height:", 1, 30, panelSettings.Frame)
	panelSettings.energyHeight:GetContent():SetPoint("TOPLEFT",  previousFrame, "BOTTOMLEFT", 0, 5)

	previousFrame = panelSettings.energyHeight:GetContent()

    panelSettings.energyFontSize = layoutMappingToUI:new()
    panelSettings.energyFontSize:CreateUI("", "Energy Font Size:", 1, 30, panelSettings.Frame)
    panelSettings.energyFontSize:GetContent():SetPoint("TOPLEFT",  previousFrame, "BOTTOMLEFT", 0, 5)

    previousFrame = panelSettings.energyFontSize:GetContent()

	panelSettings.EnergyTextBordered = checkboxWrapper:new()
	panelSettings.EnergyTextBordered:CreateUI("EnergyTextBordered", "Energy Text is bordered:", panelSettings.Frame)
	panelSettings.EnergyTextBordered:GetContent():SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 2)
	panelSettings.EnergyTextBordered:GetContent():SetLabelPos("left")

	previousFrame = panelSettings.EnergyTextBordered:GetContent()

	self.callingRuler = MereHealingFrames.Config.UI.Utilities.CreateRuler(panelSettings.Frame)
	self.callingRuler:SetPoint("TOP", previousFrame, "BOTTOM", nil, 5)

	panelSettings.callingColouredText = checkboxWrapper:new()
	panelSettings.callingColouredText:CreateUI("callingColouredText", "Player Name is calling coloured:", panelSettings.Frame)
	panelSettings.callingColouredText:GetContent():SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 10)
	panelSettings.callingColouredText:GetContent():SetLabelPos("left")

	previousFrame = panelSettings.callingColouredText:GetContent()

	panelSettings.borderPlayerName = checkboxWrapper:new()
	panelSettings.borderPlayerName:CreateUI("BorderPlayerName", "Player Name has a border around it:", panelSettings.Frame)
	panelSettings.borderPlayerName:GetContent():SetPoint("TOPLEFT", previousFrame, "TOPRIGHT", 20, 0)
	panelSettings.borderPlayerName:GetContent():SetLabelPos("left")

    panelSettings.nameFontSize = layoutMappingToUI:new()
    panelSettings.nameFontSize:CreateUI("", "Name Font Size:", 1, 30, panelSettings.Frame)
    panelSettings.nameFontSize:GetContent():SetPoint("TOPLEFT",  previousFrame, "BOTTOMLEFT", 0, 5)

    previousFrame = panelSettings.nameFontSize:GetContent()

    panelSettings.absorbShown = checkboxWrapper:new()
    panelSettings.absorbShown:CreateUI("absorbShown", "Absorbs are shown as a border around the panels:", panelSettings.Frame)
    panelSettings.absorbShown:GetContent():SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", 0, 0)
    panelSettings.absorbShown:GetContent():SetLabelPos("left")

    previousFrame = panelSettings.absorbShown:GetContent()

    panelSettings.borderSize = layoutMappingToUI:new()
    panelSettings.borderSize:CreateUI("", "Panel border size:", 1, 30, panelSettings.Frame)
    panelSettings.borderSize:GetContent():SetPoint("TOPLEFT",  previousFrame, "BOTTOMLEFT", 0, 5)

    previousFrame = panelSettings.borderSize:GetContent()

	panelSettings.healthFormattingDropdown.Event.ItemSelect = function (item, value, index) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "HealthTextFormatter", index) end
	panelSettings.manaFormattingDropdown.Event.ItemSelect = function (item, value, index) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "ManaTextFormatter", index) end
	panelSettings.energyFormattingDropdown.Event.ItemSelect = function (item, value, index) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "EnergyTextFormatter", index) end

	panelSettings.healthRoundingDropdown.Event.ItemSelect = function (item, value, index) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "HealthTextRounding", index) end
	panelSettings.manaRoundingDropdown.Event.ItemSelect = function (item, value, index) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "ManaTextRounding", index) end
	panelSettings.energyRoundingDropdown.Event.ItemSelect = function (item, value, index) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "EnergyTextRounding", index) end

	panelSettings.manaCheckBox:SetCallback(function(layout, value) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "ShowMana", value) end)
	panelSettings.energyCheckBox:SetCallback(function(layout, value) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "ShowEnergy", value) end)
	panelSettings.manaHeight:SetCallback(function (layoutname, value) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "ManaHeight", value) end)
	panelSettings.energyHeight:SetCallback(function (layoutname, value) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "EnergyHeight", value) end)

    panelSettings.nameFontSize:SetCallback(function (layoutname, value) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "NameFontSize", value) end)
    panelSettings.healthFontSize:SetCallback(function (layoutname, value) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "HealthFontSize", value) end)
    panelSettings.manaFontSize:SetCallback(function (layoutname, value) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "ManaFontSize", value) end)
    panelSettings.energyFontSize:SetCallback(function (layoutname, value) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "EnergyFontSize", value) end)

    panelSettings.callingColouredText:SetCallback(function (layoutname, value) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "callingColouredText", value) end)
	panelSettings.borderPlayerName:SetCallback(function (layoutname, value) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "borderPlayerName", value) end)

    -- really these should merge into a drop down, something for the future
    panelSettings.callingColouredHealth:SetCallback(function (layoutname, value)
        if (value) then
            self.panelSettings.roleColouredHealth:SetCurrentValue(false, true)
            MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "roleColouredHealth", false)
        end
        MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "callingColouredHealth", value)
    end)

    panelSettings.roleColouredHealth:SetCallback(function (layoutname, value)
        if (value) then
            self.panelSettings.callingColouredHealth:SetCurrentValue(false, true)
            MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "callingColouredHealth", false)
        end
        MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "roleColouredHealth", value)
    end)

	panelSettings.HealthTextBordered:SetCallback(function (layoutname, value) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "HealthTextBordered", value) end)
	panelSettings.ManaTextBordered:SetCallback(function (layoutname, value) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "ManaTextBordered", value) end)
	panelSettings.EnergyTextBordered:SetCallback(function (layoutname, value) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "EnergyTextBordered", value) end)

    panelSettings.absorbShown:SetCallback(function (layoutname, value) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "absorbShown", value) end)

    panelSettings.borderSize:SetCallback(function (layoutname, value) MereHealingFrames.Config.UI.Layouts.ChangePanelSetting(self, "borderSize", value) end)

    --local bottom = aboveFrame:GetBottom() + (panelSettings.BottomSlotsRuler:GetHeight() * 2)
    panelSettings.Frame:SetHeight(previousFrame:GetBottom() + 2)

    panelSettings.panelSettingsScrollView:SetPoint("TOPLEFT", panelSettings.tabFrame, "TOPLEFT", 0, 0)
    panelSettings.panelSettingsScrollView:SetPoint("BOTTOMRIGHT", panelSettings.tabFrame, "BOTTOMRIGHT", 0, 0)
    panelSettings.panelSettingsScrollView:SetContent(panelSettings.Frame)

	return panelSettings.tabFrame
end

function MereHealingFrames.Config.UI.Layouts:ChangePanelSetting(field, value)
	MereHealingFrames.Debug(3, "Changing setting %s, to %s", field, tostring(value))
	self.layout.PanelSettings[field] = value
	self.layout:RefreshPanelSettings()
end

function MereHealingFrames.Config.UI.Layouts:RefreshPanelSettings()
	local panelSetting = self.layout.PanelSettings

	self.panelSettings.healthFormattingDropdown:SetSelectedValue(panelSetting.HealthTextFormatter, true)
	self.panelSettings.manaFormattingDropdown:SetSelectedValue(panelSetting.ManaTextFormatter, true)
	self.panelSettings.energyFormattingDropdown:SetSelectedValue(panelSetting.EnergyTextFormatter, true)

	self.panelSettings.healthRoundingDropdown:SetSelectedValue(panelSetting.HealthTextRounding, true)
	self.panelSettings.manaRoundingDropdown:SetSelectedValue(panelSetting.ManaTextRounding, true)
	self.panelSettings.energyRoundingDropdown:SetSelectedValue(panelSetting.EnergyTextRounding, true)

	self.panelSettings.energyHeight:SetCurrentValue(panelSetting.EnergyHeight, true)
	self.panelSettings.manaHeight:SetCurrentValue(panelSetting.ManaHeight, true)

	self.panelSettings.energyCheckBox:SetCurrentValue(panelSetting.ShowEnergy, true)
	self.panelSettings.manaCheckBox:SetCurrentValue(panelSetting.ShowMana, true)

	self.panelSettings.HealthTextBordered:SetCurrentValue(panelSetting.HealthTextBordered, true)
	self.panelSettings.ManaTextBordered:SetCurrentValue(panelSetting.ManaTextBordered, true)
	self.panelSettings.EnergyTextBordered:SetCurrentValue(panelSetting.EnergyTextBordered, true)

	self.panelSettings.callingColouredText:SetCurrentValue(panelSetting.callingColouredText, true)
	self.panelSettings.borderPlayerName:SetCurrentValue(panelSetting.borderPlayerName, true)
	self.panelSettings.callingColouredHealth:SetCurrentValue(panelSetting.callingColouredHealth, true)
    self.panelSettings.roleColouredHealth:SetCurrentValue(panelSetting.roleColouredHealth, true)

    self.panelSettings.nameFontSize:SetCurrentValue(panelSetting.NameFontSize, true)
    self.panelSettings.healthFontSize:SetCurrentValue(panelSetting.HealthFontSize, true)
    self.panelSettings.manaFontSize:SetCurrentValue(panelSetting.ManaFontSize, true)
    self.panelSettings.energyFontSize:SetCurrentValue(panelSetting.EnergyFontSize, true)

    self.panelSettings.absorbShown:SetCurrentValue(panelSetting.absorbShown, true)

    self.panelSettings.borderSize:SetCurrentValue(panelSetting.borderSize, true)
	--	CallingColouredHealthBar  = false,
end

local roleFilterMappings = {
	tank = "Tank",
	heal = "Healer",
	dps = "DPS",
	support = "Support",
	}

local callingFilterMappings = {
	cleric = "Cleric",
	mage = "Mage",
	rogue = "Rogue",
	warrior = "Warrior",
	}

local groupingFilterMappings = {
	[1] = "Group 1",
	[2] = "Group 2",
	[3] = "Group 3",
	[4] = "Group 4",
}

function MereHealingFrames.Config.UI.Layouts:CreateFilteringTab()

	self.filtering = {}
	self.filtering.Frame = UI.CreateFrame("Frame", "LayoutFilteringTab", self:GetContent())

	self.filtering.RoleLabel = UI.CreateFrame("Text", "RoleFilteringLabel", self.filtering.Frame)
	self.filtering.RoleLabel:SetText("Roles to display (may need a /reloadui to take effect)")
	self.filtering.RoleLabel:SetPoint("TOPLEFT", self.filtering.Frame, "TOPLEFT", 5, 5)

	self.filterBoxes = {}
	local previousFrame = self.filtering.RoleLabel
	local indentX = 30
	for key, displayText in pairs(roleFilterMappings) do
		self.filterBoxes[key] = checkboxWrapper:new()
		self.filterBoxes[key]:CreateUI(key, displayText, self.filtering.Frame)
		self.filterBoxes[key]:GetContent():SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 0)

		self.filterBoxes[key]:SetCallback(function (...) MereHealingFrames.Config.UI.Layouts.ChangeRoleFilterValue(self, ...) end)

		previousFrame = self.filterBoxes[key]:GetContent()
		indentX = 0
	end

	self.filtering.CallingLabel = UI.CreateFrame("Text", "CallingFilteringLabel", self.filtering.Frame)
	self.filtering.CallingLabel:SetText("Callings to display (may need a /reloadui to take effect)")
	self.filtering.CallingLabel:SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", -30, 0)

	indentX = 30
	previousFrame = self.filtering.CallingLabel
	self.callingFilterBoxes = {}
	for key, displayText in pairs(callingFilterMappings) do
		self.callingFilterBoxes[key] = checkboxWrapper:new()
		self.callingFilterBoxes[key]:CreateUI(key, displayText, self.filtering.Frame)
		self.callingFilterBoxes[key]:GetContent():SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 0)
		self.callingFilterBoxes[key]:SetCallback(function (...) MereHealingFrames.Config.UI.Layouts.ChangeCallingFilterValue(self, ...) end)

		previousFrame = self.callingFilterBoxes[key]:GetContent()
		indentX = 0
	end

	self.filtering.GroupingLabel = UI.CreateFrame("Text", "GroupingLabel", self.filtering.Frame)
	self.filtering.GroupingLabel:SetText("Groups to display (may need a /reloadui to take effect)")
	self.filtering.GroupingLabel:SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", -30, 0)

	indentX = 30
	previousFrame = self.filtering.GroupingLabel
	self.groupingFilterBoxes = {}
	for key, displayText in pairs(groupingFilterMappings) do
		self.groupingFilterBoxes[key] = checkboxWrapper:new()
		self.groupingFilterBoxes[key]:CreateUI(key, displayText, self.filtering.Frame)
		self.groupingFilterBoxes[key]:GetContent():SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 0)
		self.groupingFilterBoxes[key]:SetCallback(function (...) MereHealingFrames.Config.UI.Layouts.ChangeGroupingFilterValue(self, ...) end)

		previousFrame = self.groupingFilterBoxes[key]:GetContent()
		indentX = 0
	end

	self.sortingStyle = {}
	self.sortingStyle.label = UI.CreateFrame("Text", "SortingStyleLabel", self.filtering.Frame)
	self.sortingStyle.label:SetText("Sorting method:")
	self.sortingStyle.label:SetPoint("TOPLEFT", self.filtering.Frame, "TOPLEFT", 5, 300)

	self.sortingStyle.dropdown = UI.CreateFrame("SimpleSelect", "SortingStyleDropDown", self.filtering.Frame)
	self.sortingStyle.dropdown:SetItems( {"By Group Id", "By Name", "By Group Id, compacted (matches Rift UI)", "By Role and Name" }, {"group", "name", "compactgroup", "roleandname"})
	self.sortingStyle.dropdown:SetPoint("TOPLEFT", self.filtering.Frame, "TOPLEFT", 105, 300)
	self.sortingStyle.dropdown:SetBorder(1, 1, 1, 1, 1)
	self.sortingStyle.dropdown:ResizeToFit()
    self.sortingStyle.dropdown:SetLayer(5)

	-- index matches the 2nd list to setitems
	self.sortingStyle.dropdown.Event.ItemSelect = function (item, value, index) MereHealingFrames.Config.UI.Layouts.ChangeSortOrder(self, index) end
 	previousFrame = self.sortingStyle.label

	self.filtering.showLabel = checkboxWrapper:new()
	self.filtering.showLabel:CreateUI("", "Show Label on frame (label is always shown while configuring layout)", self.filtering.Frame)
	self.filtering.showLabel:GetContent():SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", indentX, 10)
	self.filtering.showLabel:SetCallback(function (...) MereHealingFrames.Config.UI.Layouts.toggleLabel(self) end)
    previousFrame = self.filtering.showLabel:GetContent()

    self.filtering.fillColumnsThenRows = checkboxWrapper:new()
    self.filtering.fillColumnsThenRows:CreateUI("", "Fill rows then columns", self.filtering.Frame)
    self.filtering.fillColumnsThenRows:GetContent():SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", 0, 0)
    self.filtering.fillColumnsThenRows:SetCallback(function (_, newValue) MereHealingFrames.Config.UI.Layouts.ChangeValue(self, "FillRowsThenColumns", newValue) end)

    previousFrame = self.filtering.fillColumnsThenRows:GetContent()

    self.filtering.fillRightToLeft = checkboxWrapper:new()
    self.filtering.fillRightToLeft:CreateUI("", "Fill rows right to left", self.filtering.Frame)
    self.filtering.fillRightToLeft:GetContent():SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", 0, 0)
    self.filtering.fillRightToLeft:SetCallback(function (_, newValue) MereHealingFrames.Config.UI.Layouts.ChangeValue(self, "FillRightToLeft", newValue) end)

    previousFrame = self.filtering.fillRightToLeft:GetContent()

    self.filtering.fillBottomToTop = checkboxWrapper:new()
    self.filtering.fillBottomToTop:CreateUI("", "Fill columns bottom to top", self.filtering.Frame)
    self.filtering.fillBottomToTop:GetContent():SetPoint("TOPLEFT", previousFrame, "BOTTOMLEFT", 0, 0)
    self.filtering.fillBottomToTop:SetCallback(function (_, newValue) MereHealingFrames.Config.UI.Layouts.ChangeValue(self, "FillBottomToTop", newValue) end)

    return self.filtering.Frame
end

function MereHealingFrames.Config.UI.Layouts:toggleLabel()
	self.layout.ShowNameLabel = not self.layout.ShowNameLabel
end

function MereHealingFrames.Config.UI.Layouts:CreateSpecsTab()

	self.specs = {}
	self.specs.Frame = UI.CreateFrame("Frame", "LayoutSpecsTab", self:GetContent())

	self.specs.SpecsLabel = UI.CreateFrame("Text", "LayoutSpecsLabel", self.specs.Frame)
	self.specs.SpecsLabel:SetText("Not yet implemented, this tab will allow you to pick which soul specs to display this layout in")
	self.specs.SpecsLabel:SetPoint("TOPLEFT", self.specs.Frame, "TOPLEFT", 5, 5)

	return self.specs.Frame
end

function MereHealingFrames.Config.UI.Layouts:ChangeLayoutSelection(item)
	local layout = MereHealingFrames.Layouts[item]

	if self.layout then
		self.layout:SetConfiguring(false)
	end

	for key, slider in pairs(self.layoutValues) do
		slider:SetCurrentValue(layout[key])
	end

    self.sizing.anchorDropDown:SetSelectedItem(layout.AnchorPoint, true)

	for role, _ in pairs(roleFilterMappings) do
		self.filterBoxes[role]:SetCurrentValue(layout.RoleFilter[role] or false)
	end

	for calling, _ in pairs(callingFilterMappings) do
		self.callingFilterBoxes[calling]:SetCurrentValue(layout.CallingFilter[calling] or false)
	end

	for group, _ in pairs(groupingFilterMappings) do
		self.groupingFilterBoxes[group]:SetCurrentValue(layout.GroupingFilter[group] or false)
	end

	self.sortingStyle.dropdown:SetSelectedValue(layout.orderBy, true)

	self.layout = layout
	self.filtering.showLabel:SetCurrentValue(layout.ShowNameLabel, true)
    self.filtering.fillColumnsThenRows:SetCurrentValue(layout.FillRowsThenColumns, true)
    self.filtering.fillRightToLeft:SetCurrentValue(layout.FillRightToLeft, true)
    self.filtering.fillBottomToTop:SetCurrentValue(layout.FillBottomToTop, true)

	self:RefreshPanelSettings()
	self:RefreshBuffSettingsTab()

	self.layout:SetConfiguring(true)
end

function MereHealingFrames.Config.UI.Layouts:GetContent()
	return self.Frame
end

function MereHealingFrames.Config.UI.Layouts:ChangeRoleFilterValue(key, newValue)
	if not self.layout then return end

	local filter = {}
	for key, box in pairs(self.filterBoxes) do
		if self.filterBoxes[key]:GetCurrentValue() then
			table.insert(filter, key)
		end
	end

	self.layout:SetRoleFilter(filter)
end

function MereHealingFrames.Config.UI.Layouts:ChangeCallingFilterValue(key, newValue)
	if not self.layout then return end

	local filter = {}
	for key, box in pairs(self.callingFilterBoxes) do
		filter[key] = self.callingFilterBoxes[key]:GetCurrentValue()
	end

	self.layout:SetCallingFilter(filter)
end

function MereHealingFrames.Config.UI.Layouts:ChangeGroupingFilterValue(key, newValue)
	if not self.layout then return end

	local filter = {}
	for key, box in pairs(self.groupingFilterBoxes) do
		filter[key] = self.groupingFilterBoxes[key]:GetCurrentValue()
	end

	self.layout:SetGroupingFilter(filter)
end

function MereHealingFrames.Config.UI.Layouts:ChangeSortOrder(newValue)
	if not self.layout then return end

	if not self.layout:SetOrderBy(newValue) then
		error("sort order is invalid: " .. newValue)
	end
end

function MereHealingFrames.Config.UI.Layouts:ChangeValue(key, newValue)
	if not self.layout then return end

	self.layout[key] = newValue
	self.layout:RelayPanels()
end

function MereHealingFrames.Config.UI.Layouts:ChangeAnchorPoint(vertical, horizontal)
    if not self.layout then return end
    MereHealingFrames.Debug(2, "Changing Anchor Point to %s%s", vertical, horizontal)

    self.layout:ChangeAnchorPoint(vertical,horizontal)
end

MereHealingFrames.Config.UI.Layout = {}
function MereHealingFrames.Config.UI.Layout:new (frame, layoutName, layout)
	local this = {}

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

function MereHealingFrames.Config.UI.Layouts:CreateBuffSettingsTab(tabs)
	local topOffsetY = 5
	self.buffSettings = {}
	local buffSettings = self.buffSettings

	buffSettings.Frame = UI.CreateFrame("Frame", "BuffSettingsTab", self:GetContent())
	tabs:AddTab("Icon Settings", buffSettings.Frame)

	buffSettings.TopSlider = MereHealingFrames.Config.UI.Utilities.LabelSlider:new(buffSettings.Frame, "Top Row:", 0, 10, 60)
	buffSettings.MiddleSlider = MereHealingFrames.Config.UI.Utilities.LabelSlider:new(buffSettings.Frame, "Middle Row:", 0, 10, 60)
	buffSettings.BottomSlider = MereHealingFrames.Config.UI.Utilities.LabelSlider:new(buffSettings.Frame, "Bottom Row:", 0, 10, 60)

	buffSettings.TopSlider:GetContent():SetPoint("TOPLEFT", buffSettings.Frame, "TOPLEFT", 5, 5)
	buffSettings.MiddleSlider:GetContent():SetPoint("TOPLEFT", buffSettings.TopSlider:GetContent(), "BOTTOMLEFT")
	buffSettings.BottomSlider:GetContent():SetPoint("TOPLEFT", buffSettings.MiddleSlider:GetContent(), "BOTTOMLEFT")

	buffSettings.TopSlider:SetCurrentValue(5)
	buffSettings.MiddleSlider:SetCurrentValue(0)
	buffSettings.BottomSlider:SetCurrentValue(0)

    buffSettings.TopSlider:SetCallback(function(buffSlot) MereHealingFrames.Config.UI.Layouts.UpdateBuffSetting(self, "topRow", buffSlot) end)
    buffSettings.MiddleSlider:SetCallback(function(buffSlot) MereHealingFrames.Config.UI.Layouts.UpdateBuffSetting(self, "middleRow", buffSlot) end)
    buffSettings.BottomSlider:SetCallback(function(buffSlot) MereHealingFrames.Config.UI.Layouts.UpdateBuffSetting(self, "bottomRow", buffSlot) end)

	buffSettings.TopRightToLeft = checkboxWrapper:new()
    buffSettings.TopRightToLeft:CreateUI("", "TopRightToLeft", buffSettings.Frame)
	buffSettings.TopRightToLeft:GetContent():SetText("Icons are displayed Right To Left")
	buffSettings.TopRightToLeft:GetContent():SetPoint("CENTERLEFT", buffSettings.TopSlider:GetContent(), "CENTERRIGHT", 10, 0)

	buffSettings.MiddleRightToLeft = checkboxWrapper:new()
    buffSettings.MiddleRightToLeft:CreateUI("", "MiddleRightToLeft", buffSettings.Frame)
	buffSettings.MiddleRightToLeft:GetContent():SetText("Icons are displayed Right To Left")
	buffSettings.MiddleRightToLeft:GetContent():SetPoint("CENTERLEFT", buffSettings.MiddleSlider:GetContent(), "CENTERRIGHT", 10, 0)

	buffSettings.BottomRightToLeft = checkboxWrapper:new()
    buffSettings.BottomRightToLeft:CreateUI("", "BottomRightToLeft", buffSettings.Frame)
	buffSettings.BottomRightToLeft:GetContent():SetText("Icons are displayed Right To Left")
	buffSettings.BottomRightToLeft:GetContent():SetPoint("CENTERLEFT", buffSettings.BottomSlider:GetContent(), "CENTERRIGHT", 10, 0)

    buffSettings.TopRightToLeft:SetCallback(function(_, value) MereHealingFrames.Config.UI.Layouts.UpdateBuffSetting(self, "topRightToLeft", value) end)
    buffSettings.MiddleRightToLeft:SetCallback(function(_, value) MereHealingFrames.Config.UI.Layouts.UpdateBuffSetting(self, "middleRightToLeft", value) end)
    buffSettings.BottomRightToLeft:SetCallback(function(_, value) MereHealingFrames.Config.UI.Layouts.UpdateBuffSetting(self, "bottomRightToLeft", value) end)

	local aboveFrame = buffSettings.BottomSlider:GetContent()
	buffSettings.buffSlotsRuler = MereHealingFrames.Config.UI.Utilities.CreateRuler(buffSettings.Frame, "Icon to buff slot mappings")
	buffSettings.buffSlotsRuler:SetPoint("TOP", aboveFrame, "BOTTOM", nil, 5)

	buffSettings.buffSlots = {}
	buffSettings.buffSlotScrollView = UI.CreateFrame("SimpleScrollView", "BuffSlotScroller", buffSettings.Frame)
	buffSettings.buffSlotFrame = UI.CreateFrame("Frame", "BuffSlotList", buffSettings.buffSlotScrollView)

    buffSettings.TopSlotsRuler = MereHealingFrames.Config.UI.Utilities.CreateRuler(buffSettings.buffSlotFrame, "Top Row Icons")
    buffSettings.TopSlotsRuler:SetPoint("TOP", buffSettings.buffSlotFrame , "TOP", nil, 5)

	aboveFrame = buffSettings.TopSlotsRuler
	for i=1,20 do
		local buffSlot = {}
		local buffSlotText = "Icon " .. i
		buffSlot.labelSlider = MereHealingFrames.Config.UI.Utilities.LabelSlider:new(buffSettings.buffSlotFrame, buffSlotText, 0, 20, 60)
        buffSlot.labelSlider:SetCallback(function(buffSlot) MereHealingFrames.Config.UI.Layouts.BuffIconSlot(self, i, buffSlot) end)
		buffSlot.labelSlider:GetContent():SetPoint("TOP", aboveFrame, "BOTTOM", nil, 5)
		buffSlot.labelSlider:GetContent():SetPoint("LEFT", buffSettings.buffSlotFrame, "LEFT", 5, nil)

		buffSlot.description = UI.CreateFrame("Text", "BuffSlotDescription", buffSettings.buffSlotFrame)
		buffSlot.description:SetPoint("LEFTCENTER", buffSlot.labelSlider:GetContent(), "RIGHTCENTER", 10, 0)
		buffSlot.description:SetPoint("RIGHT", buffSettings.buffSlotFrame, "RIGHT", -5, nil)

		buffSettings.buffSlots[i] = buffSlot
		aboveFrame = buffSlot.labelSlider:GetContent()
	end

    buffSettings.MiddleSlotsPosition = nil
    buffSettings.BottomSlotsPosition = nil
    buffSettings.MiddleSlotsRuler = MereHealingFrames.Config.UI.Utilities.CreateRuler(buffSettings.buffSlotFrame, "Middle Row Icons")
    buffSettings.BottomSlotsRuler = MereHealingFrames.Config.UI.Utilities.CreateRuler(buffSettings.buffSlotFrame, "Bottom Row Icons")

	local bottom = aboveFrame:GetBottom() + (buffSettings.BottomSlotsRuler:GetHeight() * 2)
	buffSettings.buffSlotFrame:SetHeight(bottom + 10)

	buffSettings.buffSlotScrollView:SetPoint("BOTTOMRIGHT", buffSettings.Frame, "BOTTOMRIGHT", -5, -5)
	buffSettings.buffSlotScrollView:SetPoint("TOPLEFT", buffSettings.buffSlotsRuler, "BOTTOMLEFT", 0, 5)
	buffSettings.buffSlotScrollView:SetContent(buffSettings.buffSlotFrame)

	return buffSettings.Frame
end

function MereHealingFrames.Config.UI.Layouts:RefreshBuffSettingsRulers()
    local buffSettings = self.buffSettings
    local buffConfig = self.layout.PanelSettings.buffConfiguration

    buffSettings.MiddleSlotsRuler:ClearPoint("TOP")
    buffSettings.BottomSlotsRuler:ClearPoint("TOP")

    if buffSettings.MiddleSlotsPosition ~= nil then
        local slider = buffSettings.buffSlots[buffSettings.MiddleSlotsPosition + 1]
        if slider then
            local aboveSlider = buffSettings.buffSlots[buffSettings.MiddleSlotsPosition]

            if aboveSlider then
                slider.labelSlider:GetContent():SetPoint("TOP", aboveSlider.labelSlider:GetContent(), "BOTTOM", nil, 5)
            else
                slider.labelSlider:GetContent():SetPoint("TOP", buffSettings.TopSlotsRuler, "BOTTOM", nil, 5)
            end
        end
    end

    if buffSettings.BottomSlotsPosition ~= nil then
        local slider = buffSettings.buffSlots[buffSettings.BottomSlotsPosition + 1]
        if slider then
            local aboveSlider = buffSettings.buffSlots[buffSettings.BottomSlotsPosition]

            if aboveSlider then
                slider.labelSlider:GetContent():SetPoint("TOP", aboveSlider.labelSlider:GetContent(), "BOTTOM", nil, 5)
            else
                slider.labelSlider:GetContent():SetPoint("TOP", buffSettings.TopSlotsRuler, "BOTTOM", nil, 5)
            end
        end
    end

    buffSettings.MiddleSlotsPosition = buffConfig.topRow
    buffSettings.BottomSlotsPosition = buffConfig.topRow + buffConfig.middleRow

    local aboveFrame
    local belowFrame

    if buffSettings.MiddleSlotsPosition == 0 then
        aboveFrame = buffSettings.TopSlotsRuler
    else
        aboveFrame = buffSettings.buffSlots[buffSettings.MiddleSlotsPosition].labelSlider:GetContent()
    end

    if buffSettings.MiddleSlotsPosition >= buffSettings.BottomSlotsPosition then
        belowFrame = nil
    else
        belowFrame = buffSettings.buffSlots[buffSettings.MiddleSlotsPosition+1].labelSlider:GetContent()
    end

    buffSettings.MiddleSlotsRuler:SetPoint("TOP", aboveFrame, "BOTTOM", nil, 5)
    if belowFrame then
        belowFrame:SetPoint("TOP", buffSettings.MiddleSlotsRuler, "BOTTOM", nil, 5)
    end

    if buffSettings.BottomSlotsPosition == buffSettings.MiddleSlotsPosition then
        aboveFrame =  buffSettings.MiddleSlotsRuler
    else
        aboveFrame = buffSettings.buffSlots[buffSettings.BottomSlotsPosition].labelSlider:GetContent()
    end

    if buffSettings.BottomSlotsPosition >= 20 then
        belowFrame = nil
    else
        belowFrame = buffSettings.buffSlots[buffSettings.BottomSlotsPosition+1].labelSlider:GetContent()
    end

    buffSettings.BottomSlotsRuler:SetPoint("TOP", aboveFrame, "BOTTOM", nil, 5)
    if belowFrame then
        belowFrame:SetPoint("TOP", buffSettings.BottomSlotsRuler, "BOTTOM", nil, 5)
    end
end

function MereHealingFrames.Config.UI.Layouts:RefreshBuffSettingsTab()
	local buffSettings = self.layout.PanelSettings.buffConfiguration
	local SlotNumbers = {};
	local CurrentSlotNames = {};

	local buffSlots = self.buffSettings.buffSlots

	self.buffSettings.TopSlider:SetCurrentValue(buffSettings.topRow)
	self.buffSettings.MiddleSlider:SetCurrentValue(buffSettings.middleRow)
	self.buffSettings.BottomSlider:SetCurrentValue(buffSettings.bottomRow)

	self.buffSettings.TopRightToLeft:SetCurrentValue(buffSettings.topRightToLeft)
	self.buffSettings.MiddleRightToLeft:SetCurrentValue(buffSettings.middleRightToLeft)
	self.buffSettings.BottomRightToLeft:SetCurrentValue(buffSettings.bottomRightToLeft)

	local buffSlotValues = buffSettings.slots
	for i = 1, 20 do
		buffSlots[i].labelSlider:SetCurrentValue(buffSlotValues[i])
		if buffSlotValues[i] == 0 then
			buffSlots[i].description:SetText("Not Used")
		else
			local trackerName, tracker = MereHealingFrames.BuffSets.GetTracker(buffSlotValues[i])
			if trackerName then
				buffSlots[i].description:SetText(trackerName)
			else
				buffSlots[i].description:SetText("Unconfigured tracker")
			end
		end
    end

    self:RefreshBuffSettingsRulers()
end

function MereHealingFrames.Config.UI.Layouts:BuffIconSlot(buffIcon, buffSlot)
    local buffSettings = self.layout.PanelSettings.buffConfiguration
    local buffSlots = self.buffSettings.buffSlots

    buffSettings.slots[buffIcon] = buffSlot
    if buffSlot == 0 then
        buffSlots[buffIcon].description:SetText("Not Used")
    else
        local trackerName, tracker = MereHealingFrames.BuffSets.GetTracker(buffSlot)
        if trackerName then
            buffSlots[buffIcon].description:SetText(trackerName)
        else
            buffSlots[buffIcon].description:SetText("Unconfigured buff tracker")
        end
    end

    self.layout:RefreshPanelSettings()
end

function MereHealingFrames.Config.UI.Layouts:UpdateBuffSetting(setting, value)
    local buffSettings = self.layout.PanelSettings.buffConfiguration

    buffSettings[setting] = value
    self.layout:RefreshPanelSettings()
    self:RefreshBuffSettingsRulers()
end