All pastes #937385 Raw Edit

Anonymous

public text v1 · immutable
·published 2008-03-10 23:51 UTC
rendered paste body
local _G = getfenv(0)
local gratuity = AceLibrary("Gratuity-2.0")
local Dewdrop = AceLibrary("Dewdrop-2.0")
local LSM3 = LibStub("LibSharedMedia-3.0")
local tablet = AceLibrary("Tablet-2.0")

local ipairs				= _G.ipairs
local next					= _G.next
local pairs					= _G.pairs
local select				= _G.select
local tonumber				= _G.tonumber
local tostring				= _G.tostring
local type					= _G.type
local unpack				= _G.unpack

local GetInventoryItemLink		= _G.GetInventoryItemLink
local GetInventoryItemTexture	= _G.GetInventoryItemTexture
local GetInventorySlotInfo		= _G.GetInventorySlotInfo
local GetItemInfo				= _G.GetItemInfo
local GetPlayerBuff				= _G.GetPlayerBuff
local GetPlayerBuffApplications	= _G.GetPlayerBuffApplications
local GetPlayerBuffName			= _G.GetPlayerBuffName
local GetPlayerBuffTexture		= _G.GetPlayerBuffTexture
local GetPlayerBuffTimeLeft		= _G.GetPlayerBuffTimeLeft
local GetPlayerBuffDispelType	= _G.GetPlayerBuffDispelType
local GetWeaponEnchantInfo		= _G.GetWeaponEnchantInfo
local GetTrackingTexture		= _G.GetTrackingTexture
local UnitBuff					= _G.UnitBuff
local UnitDebuff				= _G.UnitDebuff

local math_abs				= _G.math.abs

local strgmatch				= _G.string.gmatch
local strgsub				= _G.string.gsub
local strmatch				= _G.string.match
local strtrim				= _G.string.trim
local strutf8sub			= _G.string.utf8sub

local table_insert			= _G.table.insert
local table_remove			= _G.table.remove
local table_sort			= _G.table.sort

local RANK = _G.RANK

local L = setmetatable({}, {__index = function(self, key) return key end})

ElkBuffBars = AceLibrary("AceAddon-2.0"):new("AceConsole-2.0", "AceDB-2.0", "AceEvent-2.0", "FuBarPlugin-2.0")
-- ElkBuffBars = AceLibrary("AceAddon-2.0"):new("AceConsole-2.0", "AceDB-2.0", "AceEvent-2.0", "AceDebug-2.0", "FuBarPlugin-2.0")
local ElkBuffBars = ElkBuffBars
local EBB_Bar = _G.EBB_Bar
local EBB_BarGroup = _G.EBB_BarGroup
-- ElkBuffBars.debugFrame = ChatFrame4
-- ElkBuffBars:SetDebugging(true)

ElkBuffBars.revision = tonumber(string.sub("$Revision: 63558 $", 12, -3)) or 1

ElkBuffBars:RegisterDB("ElkBuffBarsDB")
ElkBuffBars:RegisterDefaults("profile", {
	bargroups = {},
	groupspacing = 10,
	hidebuffframe = true,
	hidetenchframe = true,
	hidetrackingframe = true,
	shiftannounce = true,
	anounceoutofparty = true,
	nameoverride = {
		BUFF = {},
		DEBUFF = {},
		TENCH = {},
		TRACKING = {},
	},
	typeoverride = {
		BUFF = {},
		DEBUFF = {},
		TENCH = {},
		TRACKING = {},
	},
})

function ElkBuffBars:AddDefaultBargroups()
	table_insert(self.db.profile.bargroups,
		{
			["bars"] = {
				["barcolor"]			= {0.3, 0.5, 1, 0.8},								-- <color set>
				["barbgcolor"]			= {0, 0.5, 1, 0.3},									-- <color set>
			},
			["filter"] = {
				["type"] = {
					["BUFF"] = true,
					["TRACKING"] = true,
				}
			},
			anchortext = "BUFFS & TRACKING",			-- <string>
		})
	table_insert(self.db.profile.bargroups,
		{
			["bars"] = {
				["barcolor"]			= {1, 0, 0, 0.8},									-- <color set>
				["barbgcolor"]			= {1, 0, 0, 0.3},									-- <color set>
			},
			["filter"] = {
				["type"] = {
					["DEBUFF"] = true,
				}
			},
			anchortext = "DEBUFFS",						-- <string>
			anchorshown = false,						-- true, false
			stickto = 1,								-- bargroup id
			stickside = "",								-- "LEFT", "RIGHT", ""
		})
	table_insert(self.db.profile.bargroups,
		{
			["bars"] = {
				["barcolor"]			= {0.5, 0, 0.5, 0.8},								-- <color set>
				["barbgcolor"]			= {0.5, 0, 0.5, 0.3},								-- <color set>
			},
			["filter"] = {
				["type"] = {
					["TENCH"] = true,
				}
			},
			anchortext = "TENCH",						-- <string>
			anchorshown = false,						-- true, false
			stickto = 2,								-- bargroup id
			stickside = "",								-- "LEFT", "RIGHT", ""
		})
end

local STICKTO_AREA = 25

local INVENTORYSLOT_MAINHAND = GetInventorySlotInfo("MainHandSlot")
local INVENTORYSLOT_SECONDARYHAND = GetInventorySlotInfo("SecondaryHandSlot")

local updates_disabled = false
local scan_happend = {}
local old_hasMainHandEnchant,	old_mainHandExpiration,	old_mainHandCharges,	old_mainHandName,	old_mainHandRank
local old_hasOffHandEnchant,	old_offHandExpiration,	old_offHandCharges,		old_offHandName,	old_offHandRank

local AO_allopts
local AO_buffsettings
local AO_groupsettings

local LSM3_font = LSM3:List("font")
local LSM3_statusbar = LSM3:List("statusbar")

ElkBuffBars.ShortName = setmetatable({}, { __index = function(self, key)
	local name = key
	local shortname = ""
	if strmatch(name, "[%(%)]") then
		name = strtrim(strgsub(strgsub(name, "%b()", ""), "  +", " "))
	end
	for word in strgmatch(name, "([^ ]+)") do
		local alpha, bravo = strutf8sub(word, 1, 1), strutf8sub(word, 2)
		if strmatch(bravo, ":") then
			shortname = shortname..alpha .. ":"
		else
			shortname = shortname..alpha
		end
	end
	self[key] = shortname
	return shortname
end, })

function ElkBuffBars:OnInitialize()
	local build = select(2, _G.GetBuildInfo())
	if not self.db.account.build or self.db.account.build ~= build or true then
		self.db.account.build = build
		self.db.account.maxtimes = nil
		self.db.account.maxcharges = nil
	end
	if not self.db.account.maxtimes then
		self.db.account.maxtimes = {
			BUFF = {},
			DEBUFF = {},
			TENCH = {},
		}
	end
	if not self.db.account.maxcharges then
		self.db.account.maxcharges = {
			BUFF = {},
			DEBUFF = {},
			TENCH = {},
		}
	end
end

function ElkBuffBars:OnEnable()
	self:OnProfileEnable()
	
	-- register events
	self:RegisterEvent("PLAYER_ENTERING_WORLD")

	self:RegisterBucketEvent("MINIMAP_UPDATE_TRACKING", .2)
	self:RegisterBucketEvent("PLAYER_AURAS_CHANGED", .2)
	self:RegisterBucketEvent("PLAYER_FOCUS_CHANGED", .2)
	self:RegisterBucketEvent("PLAYER_TARGET_CHANGED", .2)
	self:RegisterBucketEvent("UNIT_PET", .2)
	self:RegisterBucketEvent("UNIT_AURA", .2)
	self:ScheduleRepeatingEvent(self.DoUpdates, .5, self)
	
	LSM3.RegisterCallback(self, "LibSharedMedia_Registered", "LibSharedMedia_Update")
	LSM3.RegisterCallback(self, "LibSharedMedia_SetGlobal", "LibSharedMedia_Update")
	--
	self:ScanData_BUFF()
	self:ScanData_DEBUFF()
	self:ScanData_TENCH()
	self:ScanData_TRACKING()

--~ 	
--~ 	self:RegisterEvent("UNIT_INVENTORY_CHANGED")
--~ 	

	-- hide Blizzard frames
	self:PLAYER_ENTERING_WORLD()
end

--~ 	
--~ function ElkBuffBars:UNIT_INVENTORY_CHANGED(...)
--~ 	self:PrintComma("UNIT_INVENTORY_CHANGED", ...)
--~ 	self:PrintComma(string.match(GetInventoryItemLink("player", INVENTORYSLOT_MAINHAND) or "nil", "|H(item:[^|]*)|") or "nil", string.match(GetInventoryItemLink("player", INVENTORYSLOT_SECONDARYHAND) or "nil", "|H(item:[^|]*)|") or "nil")
--~ end
--~ 	

function ElkBuffBars:OnDisable()
	self:OnProfileDisable()
end

function ElkBuffBars:OnProfileEnable()
	-- add default bargroups
	if #self.db.profile.bargroups == 0 then
		self:AddDefaultBargroups()
	end
	-- check bargroups
	self:CheckLayouts()
	-- update known names
	self:UpdateKnownNames()
	-- create bargroups based on stored settings
	self:CreateBarGroups()
end

function ElkBuffBars:OnProfileDisable()
	-- recycle all bargroups
	self:RemoveBarGroups()
end

-- refresh layouts when new media is set
function ElkBuffBars:LibSharedMedia_Update(callback, type, handle)
	if type == "font" or type == "statusbar" then
		for k, v in pairs(self.bargroups) do
			v:SetLayout()
		end
	end
end

function ElkBuffBars:PLAYER_ENTERING_WORLD()
--~ 	BuffFrame:Hide()
--~ 	TemporaryEnchantFrame:Hide()
	
	self:HandleFrame_Blizzard_BuffFrame(self.db.profile.hidebuffframe)
	self:HandleFrame_Blizzard_TemporaryEnchantFrame(self.db.profile.hidetenchframe)
	self:HandleFrame_Blizzard_MiniMapTracking(self.db.profile.hidetrackingframe)
end

local hidden_blizzard_frames = {}

function ElkBuffBars:HandleFrame_Blizzard_BuffFrame(hide)
	if hide then
		BuffFrame:UnregisterEvent("PLAYER_AURAS_CHANGED")
		BuffFrame:Hide()
		hidden_blizzard_frames["BuffFrame"] = true
	elseif hidden_blizzard_frames["BuffFrame"] then
		BuffFrame:RegisterEvent("PLAYER_AURAS_CHANGED")
		BuffFrame:Show()
		BuffFrame_Update()
		hidden_blizzard_frames["BuffFrame"] = false
	end
end

function ElkBuffBars:HandleFrame_Blizzard_TemporaryEnchantFrame(hide)
	if hide then
		BuffFrame:UnregisterEvent("PLAYER_AURAS_CHANGED")
		TemporaryEnchantFrame:Hide()
		BuffFrame:SetPoint("TOPRIGHT", "TemporaryEnchantFrame", "TOPRIGHT", 0, 0)
		hidden_blizzard_frames["TemporaryEnchantFrame"] = true
	elseif hidden_blizzard_frames["TemporaryEnchantFrame"] then
		BuffFrame:RegisterEvent("PLAYER_AURAS_CHANGED")
		TemporaryEnchantFrame:Show()
		hidden_blizzard_frames["TemporaryEnchantFrame"] = false
	end
end

function ElkBuffBars:HandleFrame_Blizzard_MiniMapTracking(hide)
	if hide then
		MiniMapTracking:UnregisterEvent("MINIMAP_UPDATE_TRACKING")
		MiniMapTracking:Hide()
		hidden_blizzard_frames["MiniMapTracking"] = true
	elseif hidden_blizzard_frames["MiniMapTracking"] then
		MiniMapTracking:RegisterEvent("MINIMAP_UPDATE_TRACKING")
		MiniMapTracking:Show()
		MiniMapTracking_Update()
		hidden_blizzard_frames["MiniMapTracking"] = false
	end
end

-- -----
-- cache bars
-- -----
local barcache = {}

function ElkBuffBars:GetBar()
	if #barcache > 0 then
		return table_remove(barcache, #barcache)
	else
		return EBB_Bar:new()
	end
end

function ElkBuffBars:RecycleBar(bar)
	bar:Reset()
	table_insert(barcache, bar)
end

-- -----
-- cache bargroups
-- -----
local bargroupcache = {}

function ElkBuffBars:GetBarGroup()
	if #bargroupcache > 0 then
		return table_remove(bargroupcache, #bargroupcache)
	else
		return EBB_BarGroup:new()
	end
end

function ElkBuffBars:RecycleBarGroup(bargroup)
	bargroup:Reset()
	table_insert(bargroupcache, bargroup)
end

-- -----
-- cache datatables
-- -----
local datatablecache = {}

local function GetDataTable()
	if #datatablecache > 0 then
		return table_remove(datatablecache, #datatablecache)
	else
		return {}
	end
end

local function RecycleDataTable(dt)
	table_insert(datatablecache, dt)
end

-- -----
-- known names
-- -----
ElkBuffBars.knownnames = {
	BUFF = {},
	DEBUFF = {},
	TENCH = {},
	TRACKING = {},
}

local knownnames_validate = {
	BUFF = {},
	DEBUFF = {},
	TENCH = {},
	TRACKING = {},
}


function ElkBuffBars:AddKnownName(type, name)
	if not self.knownnames[type][name] then
		self.knownnames[type][name] = true
		AO_buffsettings.args[type].args[name] = self:GetNameOptions(type, name)
		table_insert(knownnames_validate[type], name)
		table_sort(knownnames_validate[type])
	end
end

function ElkBuffBars:UpdateKnownNames()
	for type, data in pairs(self.db.profile.nameoverride) do
		for name in pairs(data) do
			self:AddKnownName(type, name)
		end
	end
	for type, data in pairs(self.db.profile.typeoverride) do
		for name in pairs(data) do
			self:AddKnownName(type, name)
		end
	end
	for id, bg in pairs(self.db.profile.bargroups) do
		if bg.filter.names_include then
			for type, data in pairs(bg.filter.names_include) do
				for name in pairs(data) do
					self:AddKnownName(type, name)
				end
			end
		end
		if bg.filter.names_exclude then
			for type, data in pairs(bg.filter.names_exclude) do
				for name in pairs(data) do
					self:AddKnownName(type, name)
				end
			end
		end
	end
end

-- -----
-- creation/removing of bargroups
-- -----
ElkBuffBars.bargroups = {}

local function ApplyDefaults(defaults, data)
	for k, v in pairs(defaults) do
		if type(v) == "table" then
			if data[k] == nil or type(data[k]) ~= "table" then data[k] = {} end
			ApplyDefaults(v, data[k])
		else
			if data[k] == nil then data[k] = v end
		end
	end
end

local DEFAULT_LAYOUT = {
	["bars"] = {
		["icon"]				= "LEFT",											-- "LEFT", "RIGHT", false
		["iconcount"]			= true,												-- true, false
		["iconcountanchor"]		= "CENTER",											-- <anchor>
		["iconcountfont"]		= "Arial Narrow",									-- <LSM3:font>
		["iconcountfontsize"]	= 14,												-- <font size>
		["iconcountcolor"]		= {1, 1, 1, 1},										-- <color set>
		["bar"]					= true,												-- true, false
		["bgbar"]				= true,												-- true, false
		["bartexture"]			= "Otravi",											-- <LSM3:statusbar>, false
		["barright"]			= false,											-- true, false
		["textTL"]				= "NAMERANKCOUNT",									-- false, "NAME", "NAMERANK", "NAMECOUNT", "NAMERANKCOUNT", "RANK", "COUNT", "TIMELEFT", "DEBUFFTYPE"
		["textTLfont"]			= "Friz Quadrata TT",								-- <LSM3:font>
		["textTLfontsize"]		= 14,												-- <font size>
		["textTLcolor"]			= {1, 1, 1, 1},										-- <color set>
		["textTLalign"]			= "LEFT",											-- left, center, right
		["textTR"]				= "TIMELEFT",										-- false, "NAME", "NAMERANK", "NAMECOUNT", "NAMERANKCOUNT", "RANK", "COUNT", "TIMELEFT", "DEBUFFTYPE"
		["textTRfont"]			= "Friz Quadrata TT",								-- <LSM3:font>
		["textTRfontsize"]		= 14,												-- <font size>
		["textTRcolor"]			= {1, 1, 1, 1},										-- <color set>
		["textBL"]				= false,											-- false, "NAME", "NAMERANK", "NAMECOUNT", "NAMERANKCOUNT", "RANK", "COUNT", "TIMELEFT", "DEBUFFTYPE"
		["textBLfont"]			= "Friz Quadrata TT",								-- <LSM3:font>
		["textBLfontsize"]		= 14,												-- <font size>
		["textBLcolor"]			= {1, 1, 1, 1},										-- <color set>
		["textBLalign"]			= "LEFT",											-- left, center, right
		["textBR"]				= false,											-- false, "NAME", "NAMERANK", "NAMECOUNT", "NAMERANKCOUNT", "RANK", "COUNT", "TIMELEFT", "DEBUFFTYPE"
		["textBRfont"]			= "Friz Quadrata TT",								-- <LSM3:font>
		["textBRfontsize"]		= 14,												-- <font size>
		["textBRcolor"]			= {1, 1, 1},										-- <color set>
		["barcolor"]			= {0.3, 0.5, 1, 0.8},								-- <color set>
		["barbgcolor"]			= {0, 0.5, 1, 0.3},									-- <color set>
		["debufftypecolor"]		= true,												-- true, false
		["timeformat"]			= "CONDENSED",										-- "DEFAULT", "EXTENDED", "FULL", "SHORT", "CONDENSED"
		["width"]				= 250,
		["height"]				= 20,
		["tooltipanchor"]		= "default",										-- <tooltip anchor>, "default"
		timelessfull			= false,											-- true, false
		alpha					= 1,												-- alpha value
		padding					= 1,												-- 0 - 10
		abbreviate_name			= 0,												--
	},
	["filter"] = {
		["type"] = {
		}
	},
	sorting			= "timeleft",						-- timeleft, timemax
	target			= "player",							-- player, pet, target
	growup			= false,							-- true, false
	barspacing		= 0,								-- 0+
	anchortext		= "unknown bargroup",				-- <string>
	anchorshown		= true,								-- true, false
}

-- resets corrupt entries in the given layout to default values; returns a now valid layout
function ElkBuffBars:CheckLayout(layout)
	if not layout or type(layout) ~= "table" then layout = {} end
	ApplyDefaults(DEFAULT_LAYOUT, layout)
	return layout
end

function ElkBuffBars:CheckLayouts()
	local bglayouts = self.db.profile.bargroups
	for k, v in ipairs(bglayouts) do
		self:CheckLayout(v)
	end
end

function ElkBuffBars:CreateBarGroups()
	for k, v in pairs(self.bargroups) do
		self:RecycleBarGroup(v)
		self.bargroups[k] = nil
	end

	local bglayouts = self.db.profile.bargroups
	for k, v in ipairs(bglayouts) do
		self:AddBarGroup(v)
	end
	for k, v in ipairs(self.bargroups) do
		local layout = bglayouts[k]
		v:SetPosition()
		v:GetContainer():Show()
	end
end

function ElkBuffBars:RemoveBarGroups()
	for k, v in pairs(self.bargroups) do
		self:RecycleBarGroup(v)
		self.bargroups[k] = nil
		AO_groupsettings[k] = nil
	end
end

function ElkBuffBars:AddBarGroup(layout)
	if not layout then
		layout = {
			["bars"] = {
			},
			["filter"] = {
				["type"] = {
					["BUFF"] = true,
				}
			},
			anchortext = "new bargroup",				-- <string>
		}

		table_insert(self.db.profile.bargroups, layout)
	end
	local bargroup = self:GetBarGroup()
	table_insert(self.bargroups, bargroup)
	layout.id = #self.bargroups
	self:CheckLayout(layout)
	bargroup:SetLayout(layout)
	table_insert(AO_groupsettings, self:GetGroupOptions(#self.bargroups))
	return bargroup
end

function ElkBuffBars:RemoveBarGroup(id)
	local bg = table_remove(self.bargroups, id)
	table_remove(self.db.profile.bargroups, id)
	for k, v in pairs(self.bargroups) do
		local layout = v.layout
		layout.id = k
		if layout.stickto then
			if layout.stickto == id then
				-- the group we sticked to was removed
				local container = v:GetContainer()
				layout.stickto = nil
				container:ClearAllPoints()
				container:SetPoint("CENTER", UIParent, "CENTER", layout.x, layout.y)
				v:ToggleAnchor(true)
			elseif layout.stickto > id then
				layout.stickto = layout.stickto - 1
			end
		end
	end
	table_remove(AO_groupsettings)
	self:RecycleBarGroup(bg)
end

function ElkBuffBars:CopyBarLayout(target, source)
	if target == source then return end
	if not source then source = DEFAULT_LAYOUT end
	target.bars = {}
	ApplyDefaults(source.bars, target.bars)
	target.sorting = source.sorting
	self.bargroups[target.id]:SetLayout()
end

-- -----
-- buff scanning
-- -----
ElkBuffBars.buffdata = {
	focus = {},
	pet = {},
	player = {},
	target = {},
}
ElkBuffBars.debuffdata = {
	focus = {},
	pet = {},
	player = {},
	target = {},
}
ElkBuffBars.tenchdata = {}
ElkBuffBars.trackingdata = {}

function ElkBuffBars:MINIMAP_UPDATE_TRACKING()
	self:ScanData_TRACKING()

	self:DoUpdates()
end

function ElkBuffBars:PLAYER_AURAS_CHANGED()
	self:ScanData_BUFF()
	self:ScanData_DEBUFF()
	
	self:DoUpdates()
end

function ElkBuffBars:PLAYER_FOCUS_CHANGED()
	self:ScanData_Unit_BUFF("focus")
	self:ScanData_Unit_DEBUFF("focus")

	self:DoUpdates()
end

function ElkBuffBars:PLAYER_TARGET_CHANGED()
	self:ScanData_Unit_BUFF("target")
	self:ScanData_Unit_DEBUFF("target")

	self:DoUpdates()
end

function ElkBuffBars:UNIT_PET(args)
	if args["player"] then
		self:ScanData_Unit_BUFF("pet")
		self:ScanData_Unit_DEBUFF("pet")

		self:DoUpdates()
	end
end

local watched_unitids = { focus = true, pet = true, target = true }
function ElkBuffBars:UNIT_AURA(args)
	for arg in pairs(args) do
		if watched_unitids[arg] then
			self:ScanData_Unit_BUFF(arg)
			self:ScanData_Unit_DEBUFF(arg)
		end
	end

	self:DoUpdates()
end

local PATTERN_RANK = RANK.." (%d+)"
function ElkBuffBars:ScanData_BUFF()
	updates_disabled = true
	local maxtimes = self.db.account.maxtimes.BUFF
	local maxcharges = self.db.account.maxcharges.BUFF
	local datatable = self.buffdata.player
	for k, v in pairs(datatable) do
		RecycleDataTable(v)
		datatable[k] = nil
	end
	local i = 1
	while true do
		local buffIndex, untilCancelled = GetPlayerBuff(i, "HELPFUL")
		if buffIndex == 0 then break end
		local name, rank = GetPlayerBuffName(buffIndex)
		self:AddKnownName("BUFF", name)
		local tname = name..(rank and (" "..rank) or "")
		if rank then
			rank = strmatch(rank, PATTERN_RANK)
		end
		local timeleft = GetPlayerBuffTimeLeft(buffIndex)
		local timemax = timeleft
		if maxtimes[tname] and timemax < maxtimes[tname] then
			timemax = maxtimes[tname]
		else
--	if timeleft > 0 then self:Debug(i, buffIndex, name, ("%.1f"):format(timeleft / 60)) end
			maxtimes[tname] = timemax
		end
		local charges = GetPlayerBuffApplications(buffIndex) or 0
		if charges > 1 and (not maxcharges[tname] or maxcharges[tname] < charges) then
			maxcharges[tname] = charges
		end

		local dt = GetDataTable()
		dt.id				= buffIndex
		dt.name				= self.db.profile.nameoverride.BUFF[name] or name
		dt.realname			= name
		dt.rank				= rank and tonumber(rank) or nil
		dt.type				= self.db.profile.typeoverride.BUFF[name] or "BUFF"
		dt.realtype			= "BUFF"
		dt.debufftype		= nil
		dt.timeleft			= timeleft
		dt.timemax			= timemax
		dt.untilcancelled	= (untilCancelled == 1) and true or nil
		dt.charges			= charges
		dt.maxcharges		= maxcharges[tname]
		dt.icon				= GetPlayerBuffTexture(buffIndex)
		
		table_insert(datatable, dt)
		i = i + 1
	end
	scan_happend.player = true
	updates_disabled = false
end

function ElkBuffBars:ScanData_DEBUFF()
	updates_disabled = true
	local maxtimes = self.db.account.maxtimes.DEBUFF
	local maxcharges = self.db.account.maxcharges.DEBUFF
	local datatable = self.debuffdata.player
	for k, v in pairs(datatable) do
		RecycleDataTable(v)
		datatable[k] = nil
	end
	local i = 1
	while true do
		local buffIndex, untilCancelled = GetPlayerBuff(i, "HARMFUL")
		if buffIndex == 0 then break end
		local name, rank = GetPlayerBuffName(buffIndex)
		self:AddKnownName("DEBUFF", name)
		local tname = name..(rank and (" "..rank) or "")
		if rank then
			rank = strmatch(rank, PATTERN_RANK)
		end
		local timeleft = GetPlayerBuffTimeLeft(buffIndex)
		local timemax = timeleft
		if maxtimes[tname] and timemax < maxtimes[tname] then
			timemax = maxtimes[tname]
		else
--	if timeleft > 0 then self:Debug(i, buffIndex, name, ("%.1f"):format(timeleft / 60)) end
			maxtimes[tname] = timemax
		end
		local charges = GetPlayerBuffApplications(buffIndex) or 0
		if charges > 1 and (not maxcharges[tname] or maxcharges[tname] < charges) then
			maxcharges[tname] = charges
		end

		local dt = GetDataTable()
		dt.id				= buffIndex
		dt.name				= self.db.profile.nameoverride.DEBUFF[name] or name
		dt.realname			= name
		dt.rank				= rank and tonumber(rank) or nil
		dt.type				= self.db.profile.typeoverride.DEBUFF[name] or "DEBUFF"
		dt.realtype			= "DEBUFF"
		dt.debufftype		= GetPlayerBuffDispelType(buffIndex)
		dt.timeleft			= timeleft
		dt.timemax			= timemax
		dt.untilcancelled	= (untilCancelled == 1) and true or nil
		dt.charges			= charges
		dt.maxcharges		= maxcharges[tname]
		dt.icon				= GetPlayerBuffTexture(buffIndex)
		
		table_insert(datatable, dt)
		i = i + 1
	end
	scan_happend.player = true
	updates_disabled = false
end

function ElkBuffBars:ScanData_TENCH()
	updates_disabled = true
	local maxtimes = self.db.account.maxtimes.TENCH
	local maxcharges = self.db.account.maxcharges.TENCH
	for k, v in pairs(self.tenchdata) do
		RecycleDataTable(v)
		self.tenchdata[k] = nil
	end
	local hasMainHandEnchant, mainHandExpiration, mainHandCharges, hasOffHandEnchant, offHandExpiration, offHandCharges = GetWeaponEnchantInfo()
	if ( hasMainHandEnchant ) then
		local timeleft = mainHandExpiration / 1000
		local timemax = timeleft
	
		local id = INVENTORYSLOT_MAINHAND
		local name, rank = self:GetTempBuffName(id)
		self:AddKnownName("TENCH", name)
		local tname = name..(rank and (" "..rank) or "")
--		if rank then
--			rank = strmatch(rank, PATTERN_RANK)
--		end
		if maxtimes[tname] and timemax < maxtimes[tname] then
			timemax = maxtimes[tname]
		else
			maxtimes[tname] = timemax
		end
		local charges = mainHandCharges or 0
		if charges > 1 and (not maxcharges[tname] or maxcharges[tname] < charges) then
			maxcharges[tname] = charges
		end

		local dt = GetDataTable()
		dt.id				= id
		dt.name				= self.db.profile.nameoverride.TENCH[name] or name
		dt.realname			= name
		dt.rank				= rank and tonumber(rank) or nil
		dt.type				= self.db.profile.typeoverride.TENCH[name] or "TENCH"
		dt.realtype			= "TENCH"
		dt.debufftype		= nil
		dt.timeleft			= timeleft
		dt.timemax			= timemax
		dt.untilcancelled	= nil
		dt.charges			= charges
		dt.maxcharges		= maxcharges[tname]
		dt.icon				= GetInventoryItemTexture("player", id)
		
		table_insert(self.tenchdata, dt)
	end
	if ( hasOffHandEnchant ) then
		local timeleft = offHandExpiration / 1000
		local timemax = timeleft

		local id = INVENTORYSLOT_SECONDARYHAND
		local name, rank = self:GetTempBuffName(id)
		local tname = name..(rank and (" "..rank) or "")
		self:AddKnownName("TENCH", name)
--		if rank then
--			rank = strmatch(rank, PATTERN_RANK)
--		end
		if maxtimes[tname] and timemax < maxtimes[tname] then
			timemax = maxtimes[tname]
		else
			maxtimes[tname] = timemax
		end
		local charges = offHandCharges or 0
		if charges > 1 and (not maxcharges[tname] or maxcharges[tname] < charges) then
			maxcharges[tname] = charges
		end

		local dt = GetDataTable()
		dt.id				= id
		dt.name				= self.db.profile.nameoverride.TENCH[name] or name
		dt.realname			= name
		dt.rank				= rank and tonumber(rank) or nil
		dt.type				= self.db.profile.typeoverride.TENCH[name] or "TENCH"
		dt.realtype			= "TENCH"
		dt.debufftype		= nil
		dt.timeleft			= timeleft
		dt.timemax			= timemax
		dt.untilcancelled	= nil
		dt.charges			= charges
		dt.maxcharges		= maxcharges[tname]
		dt.icon				= GetInventoryItemTexture("player", id)
		
		table_insert(self.tenchdata, dt)
	end
	scan_happend.player = true
	updates_disabled = false
end

function ElkBuffBars:ScanData_TRACKING()
	updates_disabled = true
	for k, v in pairs(self.trackingdata) do
		RecycleDataTable(v)
		self.trackingdata[k] = nil
	end
	local icon = GetTrackingTexture()
	if icon then
		local name = self:GetTrackingName()
		self:AddKnownName("TRACKING", name)
		local dt = GetDataTable()
		dt.id				= 1
		dt.name				= self.db.profile.nameoverride.TRACKING[name] or name
		dt.realname			= name
		dt.rank				= nil
		dt.type				= self.db.profile.typeoverride.TRACKING[name] or "TRACKING"
		dt.realtype			= "TRACKING"
		dt.debufftype		= nil
		dt.timeleft			= 1
		dt.timemax			= 1
		dt.untilcancelled	= true
		dt.charges			= 0
		dt.maxcharges		= nil
		dt.icon				= icon
		
		table_insert(self.trackingdata, dt)
	end
	scan_happend.player = true
	updates_disabled = false
end

function ElkBuffBars:ScanData_Unit_BUFF(unit)
	local maxcharges = self.db.account.maxcharges.BUFF
	local datatable = self.buffdata[unit]
	if not datatable then return end
	updates_disabled = true
	for k, v in pairs(datatable) do
		RecycleDataTable(v)
		datatable[k] = nil
	end
	local i = 1
	while true do
		local name, rank, icon, charges, timemax, timeleft = UnitBuff(unit, i)
		if not icon then break end
		local tname = name..(rank and (" "..rank) or "")
		self:AddKnownName("BUFF", name)
		if rank then
			rank = strmatch(rank, PATTERN_RANK)
		end
		if timemax then
			self.db.account.maxtimes.BUFF[tname] = timemax
		end
		charges = charges or 0
		if charges > 1 and (not maxcharges[tname] or maxcharges[tname] < charges) then
			maxcharges[tname] = charges
		end

		local dt = GetDataTable()
		dt.id				= i
		dt.name				= self.db.profile.nameoverride.BUFF[name] or name
		dt.realname			= name
		dt.rank				= rank and tonumber(rank) or nil
		dt.type				= (self.db.profile.typeoverride.BUFF[name] or "BUFF")
		dt.realtype			= "BUFF"
		dt.debufftype		= nil
		dt.timeleft			= timeleft or 1
		dt.timemax			= timemax or 1
		dt.untilcancelled	= ((not timemax) or timemax == 0) and true or nil
		dt.charges			= charges
		dt.maxcharges		= maxcharges[tname]
		dt.icon				= icon
		
		table_insert(datatable, dt)
		i = i + 1
	end
	scan_happend[unit] = true
	updates_disabled = false
end

function ElkBuffBars:ScanData_Unit_DEBUFF(unit)
	local maxcharges = self.db.account.maxcharges.DEBUFF
	local datatable = self.debuffdata[unit]
	if not datatable then return end
	updates_disabled = true
	for k, v in pairs(datatable) do
		RecycleDataTable(v)
		datatable[k] = nil
	end
	local i = 1
	while true do
		local name, rank, icon, charges, debuffType, timemax, timeleft = UnitDebuff(unit, i);
		if not icon then break end
		local tname = name..(rank and (" "..rank) or "")
		self:AddKnownName("DEBUFF", name)
		if rank then
			rank = strmatch(rank, PATTERN_RANK)
		end
		if timemax then
			self.db.account.maxtimes.DEBUFF[tname] = timemax
		end
		charges = charges or 0
		if charges > 1 and (not maxcharges[tname] or maxcharges[tname] < charges) then
			maxcharges[tname] = charges
		end

		local dt = GetDataTable()
		dt.id				= i
		dt.name				= self.db.profile.nameoverride.DEBUFF[name] or name
		dt.realname			= name
		dt.rank				= rank and tonumber(rank) or nil
		dt.type				= (self.db.profile.typeoverride.DEBUFF[name] or "DEBUFF")
		dt.realtype			= "DEBUFF"
		dt.debufftype		= debuffType
		dt.timeleft			= timeleft or 1
		dt.timemax			= timemax or 1
		dt.untilcancelled	= ((not timemax) or timemax == 0) and true or nil
		dt.charges			= charges
		dt.maxcharges		= maxcharges[tname]
		dt.icon				= icon
		
		table_insert(datatable, dt)
		i = i + 1
	end
	scan_happend[unit] = true
	updates_disabled = false
end

local roman_to_arabic = setmetatable({I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, M = 1000}, {__index=function(self, roman)
	local arabic = 0
	local maxval = 0
	for i = roman:len(), 1, -1 do
		local digitval = self[roman:sub(i,i)]
		if digitval < maxval then
			arabic = arabic - digitval
		else
			arabic = arabic + digitval
			maxval = digitval
		end
	end
	self[roman] = arabic
	return arabic
end})

function ElkBuffBars:GetTempBuffName(id)
	local rank
	gratuity:SetInventoryItem("player", id)
	local _, _, buffname = gratuity:Find("^(.+) %(%d+ [^%)]+%)$")
	if buffname then
		buffname = strgsub(buffname, " %(%d+ [^%)]+%)", "") -- remove 2nd brackets for buffs with charges
		local tname, trank = strmatch(buffname, "(.*) (%d*)$")
		if tname then
			buffname = tname
			rank = trank
		else
			local tname, trank = strmatch(buffname, "(.*) ([CDILMVX]*)$")
			if tname then
				buffname = tname
				rank = roman_to_arabic[trank]
			end
		end
		return buffname, rank
	end
	local itemlink = GetInventoryItemLink("player", id)
	if itemlink then
		local name = GetItemInfo(itemlink)
		return name or "Weapon "..id
	end
	return "Weapon "..id
end

function ElkBuffBars:GetTrackingName()
	local name, texture, active, category
	local count = GetNumTrackingTypes()
	for id=1, count do
		name, texture, active, category  = GetTrackingInfo(id)
		if active then
			return name
		end
	end
	return NONE
end

--
--
--
function ElkBuffBars:UpdateTimes(unit)
	for k, v in pairs(self.buffdata[unit]) do
		if not v.untilcancelled then
			local timemax, timeleft = select(5, UnitBuff(unit, v.id))
			if not timemax or timemax == 0 or timeleft > v.timeleft then
				self:ScanData_Unit_BUFF(unit)
				break
			end
			v.timeleft = timeleft
		end
	end

	for k, v in pairs(self.debuffdata[unit]) do
		if not v.untilcancelled then
			local timemax, timeleft = select(6, UnitDebuff(unit, v.id))
			if not timemax or timemax == 0 or timeleft > v.timeleft then
				self:ScanData_Unit_DEBUFF(unit)
				break
			end
			v.timeleft = timeleft
		end
	end
end

function ElkBuffBars:DoUpdates()
	if updates_disabled then return end
	
	for k, v in pairs(self.buffdata.player) do
		if not v.untilcancelled then
			local timeleft = GetPlayerBuffTimeLeft(v.id)
			if timeleft > v.timeleft then
				self:ScanData_BUFF()
				break
			end
			v.timeleft = timeleft
		end
	end

	for k, v in pairs(self.debuffdata.player) do
		if not v.untilcancelled then
			local timeleft = GetPlayerBuffTimeLeft(v.id)
			if timeleft > v.timeleft then
				self:ScanData_DEBUFF()
				break
			end
			v.timeleft = timeleft
		end
	end

	-- check for changed weaponbuffs
	local hasMainHandEnchant, mainHandExpiration, mainHandCharges, hasOffHandEnchant, offHandExpiration, offHandCharges = GetWeaponEnchantInfo()
	local mainHandName, mainHandRank
	if hasMainHandEnchant then
		mainHandName, mainHandRank = self:GetTempBuffName(INVENTORYSLOT_MAINHAND)
	end
	local offHandName, offHandRank
	if hasOffHandEnchant then
		offHandName, offHandRank = self:GetTempBuffName(INVENTORYSLOT_SECONDARYHAND)
	end
	if hasMainHandEnchant ~= old_hasMainHandEnchant or (mainHandExpiration or 0) > (old_mainHandExpiration or 0) or mainHandCharges ~= old_mainHandCharges or mainHandName ~= old_mainHandName or mainHandRank ~= old_mainHandRank
		or hasOffHandEnchant ~= old_hasOffHandEnchant or (offHandExpiration or 0) > (old_offHandExpiration or 0) or offHandCharges ~= old_offHandCharges or offHandName ~= old_offHandName or offHandRank ~= old_offHandRank then
		self:ScanData_TENCH()
		old_hasMainHandEnchant = hasMainHandEnchant
		old_mainHandCharges = mainHandCharges
		old_mainHandName = mainHandName
		old_mainHandRank = mainHandRank
		old_hasOffHandEnchant = hasOffHandEnchant
		old_offHandCharges = offHandCharges
		old_offHandName = offHandName
		old_offHandRank = offHandRank
	else
		for k, v in pairs(self.tenchdata) do
			if v.id == INVENTORYSLOT_MAINHAND then
				v.timeleft = mainHandExpiration / 1000
			end
			if v.id == INVENTORYSLOT_SECONDARYHAND then
				v.timeleft = offHandExpiration / 1000
			end
		end
	end
	old_mainHandExpiration = mainHandExpiration
	old_offHandExpiration = offHandExpiration

	self:UpdateTimes("focus")
	self:UpdateTimes("pet")
	self:UpdateTimes("target")

	-- if we did a scan, update bar data
	if next(scan_happend) then
		for k, v in pairs(self.bargroups) do
			v:UpdateData(scan_happend)
		end
		for k in pairs(scan_happend) do
			scan_happend[k] = nil
		end
	else
		for k, v in pairs(self.bargroups) do
			v:UpdateTimeleft()
		end
	end
end

function ElkBuffBars:StickGroup(bargroup)
	local layout = bargroup.layout
	local id = layout.id
	local growup = layout.growup
	local container = bargroup:GetContainer()
	local base_y = growup and container:GetBottom() or container:GetTop()
	local base_left = container:GetLeft()
	local base_right = container:GetRight()
	layout.stickto = nil
--	self:Print("Sticking bargroup", id)
	for k, v in pairs(self.bargroups) do
		local comp_container = v:GetContainer()
		local comp_y = growup and comp_container:GetTop() or comp_container:GetBottom()
		if math_abs(comp_y - base_y) < STICKTO_AREA then
			-- we are on the same y-area
			local comp_left = comp_container:GetLeft()
			local comp_right = comp_container:GetRight()
			local dist_left = math_abs(base_left - comp_left)
			local dist_mid = math_abs((base_left + base_right) - (comp_left + comp_right)) / 2
			local dist_right = math_abs(base_right - comp_right)
			if dist_left <= STICKTO_AREA or dist_mid <= STICKTO_AREA or dist_right <= STICKTO_AREA then
--				self:Print(" - sticking to bargroup ", k)
				-- we are also on the same x-area
				-- check if we would loop-stick to ourself
				local parent = v
				local hasloop = false
				while parent.layout.stickto do
					if parent.layout.stickto == id then
--						self:Print("   - LOOP FOUND!")
						hasloop = true
						break
					end
					parent = self.bargroups[parent.layout.stickto]
				end
				if not hasloop then
					-- we have found a valid group to stick to
					layout.stickto = k
					local stickdist = STICKTO_AREA
					if dist_mid <= STICKTO_AREA then
--~ 						self:Print("   - SUCCESS! -> middle")
						layout.stickside = ""
						stickdist = dist_mid
					end
					if dist_left <= STICKTO_AREA and dist_left < stickdist then
--~ 						self:Print("   - SUCCESS! -> left")
						layout.stickside = "LEFT"
						stickdist = dist_left
					end
					if dist_right <= STICKTO_AREA and dist_right < stickdist then
--~ 						self:Print("   - SUCCESS! -> right")
						layout.stickside = "RIGHT"
						stickdist = dist_right
--~ 					else
--~ 						self:Print("   - |cffff0000ERROR|r")
					end
					bargroup:SetPosition()
					return true
				end
			end
		end
	end
	return false
end

-- -----
-- FuBar stuff
-- -----
ElkBuffBars.hasIcon = true	-- icon by Jakobud @ wowace forums
ElkBuffBars.hasNoColor = true
ElkBuffBars.clickableTooltip = true
ElkBuffBars.hideWithoutStandby = true
ElkBuffBars.independentProfile = true
ElkBuffBars.cannotDetachTooltip = true

function ElkBuffBars:OnTextUpdate()
	self:SetText("ElkBuffBars")
end

function ElkBuffBars:OnTooltipUpdate()
	local cat = tablet:AddCategory(
		'columns', 2,
		'text', L["bargroup"],
		'text2', L["type"],
		'hideBlankLine', true,
		'showWithoutChildren', true
	)
	for k, v in ipairs(self.bargroups) do
		cat:AddLine(	"text",		tostring(k)..". "..(v.layout.anchortext or "???"),
						"text2",	v.layout.target,
						"hasCheck",	true,
						"checked",	v.layout.anchorshown,
						"func",		"ToggleAnchor",
						"arg1",		v
					)
	end
end

-- -----
-- AceOption table
-- -----
AO_buffsettings = {
	type = "group", name = L["Buffs Settings"], desc = L["Change name and type for known buffs"], args = {
		BUFF = {
			type = "group", name = "BUFF", desc = "BUFF", args = {},
		},
		DEBUFF = {
			type = "group", name = "DEBUFF", desc = "DEBUFF", args = {},
		},
		TENCH = {
			type = "group", name = "TENCH", desc = "TENCH", args = {},
		},
		TRACKING = {
			type = "group", name = "TRACKING", desc = "TRACKING", args = {},
		},
	},
	order = 101,
}

AO_groupsettings = {}

AO_allopts = {
	type = "group", args = {
		buffsettings = AO_buffsettings,
		groupsettings = {
			type = "group", name = L["Group Settings"], desc = L["Changes the settings for the bargroups"], args = AO_groupsettings,
			order = 102,
		},
		newgroup = {
			type = "execute", name = L["New Group"], desc = L["Creates a new bargroup"],
			func = function()
					local bg = ElkBuffBars:AddBarGroup()
					bg:SetPosition()
					bg:GetContainer():Show()
				end,
			order = 103,
		},
		groupspacing = {
			type = "range", name = L["Group Spacing"], desc = L["Sets gap between anchored groups"],
			min = 0, max = 50, step = 1,
			get = function() return ElkBuffBars.db.profile.groupspacing end,
			set = function(v)
					ElkBuffBars.db.profile.groupspacing = tonumber(v)
					for k, bg in ipairs(ElkBuffBars.bargroups) do
						bg:SetPosition()
					end
				end,
			order = 104,
		},
		buffframe = {
			type = "toggle", name = L["Hide Blizzard Buff Frame"], desc = L["Toggles active hiding of the Blizzard buff frame"],
			get = function() return ElkBuffBars.db.profile.hidebuffframe end,
			set = function(v)
					ElkBuffBars.db.profile.hidebuffframe = v
					ElkBuffBars:HandleFrame_Blizzard_BuffFrame(ElkBuffBars.db.profile.hidebuffframe)
				end,
			order = 105,
		},
		tenchframe = {
			type = "toggle", name = L["Hide Blizzard TEnch Frame"], desc = L["Toggles active hiding of the Blizzard tench frame"],
			get = function() return ElkBuffBars.db.profile.hidetenchframe end,
			set = function(v)
					ElkBuffBars.db.profile.hidetenchframe = v
					ElkBuffBars:HandleFrame_Blizzard_TemporaryEnchantFrame(ElkBuffBars.db.profile.hidetenchframe)
				end,
			order = 105,
		},
		trackingframe = {
			type = "toggle", name = L["Hide Minimap Tracking Frame"], desc = L["Toggles active hiding of the minimap tracking frame"],
			get = function() return ElkBuffBars.db.profile.hidetrackingframe end,
			set = function(v)
					ElkBuffBars.db.profile.hidetrackingframe = v
					ElkBuffBars:HandleFrame_Blizzard_MiniMapTracking(ElkBuffBars.db.profile.hidetrackingframe)
				end,
			order = 105,
		},
		shiftannounce = {
			type = "toggle", name = L["Shift-click to announce"], desc = L["Toggles shift-click announcing of buffs to party"],
			get = function() return ElkBuffBars.db.profile.shiftannounce end,
			set = function(v)
					ElkBuffBars.db.profile.shiftannounce = v
				end,
			order = 106,
		},
		announceoutofparty = {
			type = "toggle", name = L["Announce in /say"], desc = L["Toggles announcement of buffs in /say when not in a party"],
			get = function() return ElkBuffBars.db.profile.announceoutofparty end,
			set = function(v)
					ElkBuffBars.db.profile.announceoutofparty = v
				end,
			order = 107,
		},
	}
}

local typeoverride_validate = {BUFF = "BUFF", DEBUFF = "DEBUFF", TENCH = "TENCH", TRACKING = "TRACKING", [""] = L["default"]}
function ElkBuffBars:GetNameOptions(type, name)
	return {
		type = "group", name = name, desc = name, args = {
			name = {
				type = "text", name = L["Shown Name"], desc = L["Sets the name to show"], usage = "none",
				get = function() return ElkBuffBars.db.profile.nameoverride[type][name] or "" end,
				set = function(v) ElkBuffBars.db.profile.nameoverride[type][name] = v ~= "" and v or nil end,
			},
			type = {
				type = "text", name = L["New Type"], desc = L["Sets the new type"],
				get = function() return ElkBuffBars.db.profile.typeoverride[type][name] or "" end,
				set = function(v) ElkBuffBars.db.profile.typeoverride[type][name] = (v ~= "" and v ~= type) and v or nil end,
				validate = typeoverride_validate,
			}
		}
	}
end

local function SetNameFilter(groupid, white, type, name, value)
	local bg = ElkBuffBars.bargroups[groupid]
	local filter = bg.layout.filter
	local ftname = white and "names_include" or "names_exclude"
	if value then
		if not filter[ftname] then
			filter[ftname] = {}
		end
		if not filter[ftname][type] then
			filter[ftname][type] = {}
		end
		filter[ftname][type][name] = true
	elseif filter[ftname] and filter[ftname][type] then
		filter[ftname][type][name] = nil
		local hasdata = false
		for _ in pairs(filter[ftname][type]) do
			hasdata = true
			break
		end
		if not hasdata then
			filter[ftname][type] = nil
		end
		hasdata = false
		for _ in pairs(filter[ftname]) do
			hasdata = true
			break
		end
		if not hasdata then
			filter[ftname] = nil
		end
	end
	bg:UpdateData()
end

local groupoptionscache = {}
function ElkBuffBars:GetGroupOptions(id)
	if not groupoptionscache[id] then
		groupoptionscache[id] = {
			type = "group", name = (L["Group %d"]):format(id), desc = (L["Settings for Group %d"]):format(id), args = {
				anchorshown = {
					type = "toggle", name = L["Show Anchor"], desc = L["Toggles Anchor"],
					get = function() return ElkBuffBars.db.profile.bargroups[id].anchorshown end,
					set = function() ElkBuffBars.bargroups[id]:ToggleAnchor() end,
					order = 101,
				},
				anchortext = {
					type = "text", name = L["Name"], desc = L["Sets the group's name"], usage = "",
					get = function() return ElkBuffBars.db.profile.bargroups[id].anchortext end,
					set = function(v)
							local bg = ElkBuffBars.bargroups[id]
							bg.layout.anchortext = v
							if bg.layout.anchorshown then
								bg:ToggleAnchor(true)
							end
						end,
					order = 102,
				},
				bars = {
					type = "group", name = L["Bar Layout"], desc = L["Sets the layout for this group's bars"], args = {
						bar = {
							type = "group", name = L["Bar"], desc = L["Settings for the statusbar"], args = {
								bar = {
									type = "toggle", name = L["Show Statusbar"], desc = L["Toggles display of the statusbar"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.bar end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.bar = v
											bg:SetLayout()
										end,
									order = 101,
								},
								bartexture = {
									type = "text", name = L["Bar Texture"], desc = L["Sets the bar texture"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.bartexture end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.bartexture = v
											bg:SetLayout()
										end,
									validate = LSM3_statusbar,
									order = 102,
								},
								barcolor = {
									type = "color", name = L["Bar Color"], desc = L["Sets the color for the bar"],
									get = function() return unpack(ElkBuffBars.db.profile.bargroups[id].bars.barcolor) end,
									set = function(r, g, b, a)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.barcolor[1] = r
											bg.layout.bars.barcolor[2] = g
											bg.layout.bars.barcolor[3] = b
											bg.layout.bars.barcolor[4] = a
											bg:SetLayout()
											if bg.layout.anchorshown then
												bg:ToggleAnchor(true)
											end
										end,
									hasAlpha = true,
									order = 103,
								}, -- <color set>
								bgbar = {
									type = "toggle", name = L["Show Background"], desc = L["Toggles display of the bar background"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.bgbar end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.bgbar = v
											bg:SetLayout()
										end,
									order = 104,
								},
								barbgcolor = {
									type = "color", name = L["Background Color"], desc = L["Sets the color for the bar's background"],
									get = function() return unpack(ElkBuffBars.db.profile.bargroups[id].bars.barbgcolor) end,
									set = function(r, g, b, a)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.barbgcolor[1] = r
											bg.layout.bars.barbgcolor[2] = g
											bg.layout.bars.barbgcolor[3] = b
											bg.layout.bars.barbgcolor[4] = a
											bg:SetLayout()
										end,
									hasAlpha = true,
									order = 105,
								}, -- <color set>
								debufftypecolor = {
									type = "toggle", name = L["Debuff Coloring"], desc = L["Toggles if the bar is colored by debuff type"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.debufftypecolor end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.debufftypecolor = v
											bg:UpdateBars()
										end,
									order = 106,
								},
								barright = {
									type = "toggle", name = L["Bar Direction LTR"], desc = L["Toggles if the bar depletes from left to right"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.barright end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.barright = v
											bg:SetLayout()
										end,
									order = 107,
								},
								timelessfull = {
									type = "toggle", name = L["Full bars for timeless"], desc = L["Toggles full bars for timeless buffs"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.timelessfull end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.timelessfull = v
											bg:UpdateData()
										end,
									order = 108,
								},
							},
							order = 101,
						},
						icon = {
							type = "group", name = L["Icon"], desc = L["Settings for the icon"], args = {
								icon = {
									type = "text", name = L["Position"], desc = L["Sets icon showing"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.icon or "false" end,
									set = function(v)
											if v == "false" then v = false end
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.icon = v
											bg:SetLayout()
										end,
									validate = {["false"] = L["hide"], ["LEFT"] = "Left Side", ["RIGHT"] = "Right Side"},
									order = 101,
								}, -- "LEFT", "RIGHT", false
								iconcount = {
									type = "toggle", name = L["Buff Stacks - Show"], desc = L["Toggles showing of buff stacks on the icon"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.iconcount end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.iconcount = v
											bg:SetLayout()
										end,
									order = 102,
								}, -- true, false
								iconcountanchor = {
									type = "text", name = L["Buff Stacks - Anchor"], desc = L["Sets the anchor for the buff stacks on the icon"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.iconcountanchor end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.iconcountanchor = v
											bg:SetLayout()
										end,
									validate = {"TOPLEFT", "TOP", "TOPRIGHT", "LEFT", "CENTER", "RIGHT", "BOTTOMLEFT", "BOTTOM", "BOTTOMRIGHT"},
									order = 103,
								}, -- <anchor>
								iconcountfont = {
									type = "text", name = L["Buff Stacks - Font"], desc = L["Sets the font for the buff stacks on the icon"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.iconcountfont end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.iconcountfont = v
											bg:SetLayout()
										end,
									validate = LSM3_font,
									order = 104
								}, -- <LSM3:font>
								iconcountfontsize =  {
									type = "range", name = L["Buff Stacks - Font Size"], desc = L["Sets the font size for the buff stacks on the icon"],
									min = 4, max = 32, step = 1,
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.iconcountfontsize end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.iconcountfontsize = tonumber(v)
											bg:SetLayout()
										end,
									order = 105,
								}, -- <font size>
								iconcountcolor = {
									type = "color", name = L["Buff Stacks - Font Color"], desc = L["Sets the font color for the buff stacks on the icon"],
									get = function() return unpack(ElkBuffBars.db.profile.bargroups[id].bars.iconcountcolor) end,
									set = function(r, g, b, a)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.iconcountcolor[1] = r
											bg.layout.bars.iconcountcolor[2] = g
											bg.layout.bars.iconcountcolor[3] = b
											bg.layout.bars.iconcountcolor[4] = a
											bg:SetLayout()
										end,
									hasAlpha = true,
									order = 106,
								}, -- <color set>
							},
							order = 102
						},
						texttl = {
							type = "group", name = L["Text topleft"], desc = L["Settings for the topleft text"], args = {
								textTL = {
									type = "text", name = L["Text shown"], desc = L["Sets the text which is shown"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textTL or "false" end,
									set = function(v)
											if v == "false" then v = false end
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textTL = v
											bg:SetLayout()
										end,
									validate = {["false"] = L["hide"], ["NAME"] = L["Name"], ["NAMERANK"] = L["Name, Rank"], ["NAMECOUNT"] = L["Name, Count"], ["NAMERANKCOUNT"] = L["Name, Rank, Count"], ["RANK"] = L["Rank"], ["COUNT"] = L["Count"], ["TIMELEFT"] = L["Time Left"], ["DEBUFFTYPE"] = L["Debuff Type"]},
									order = 101,
								}, -- false, "NAME", "NAMERANK", "NAMECOUNT", "NAMERANKCOUNT", "RANK", "COUNT", "TIMELEFT", "DEBUFFTYPE"
								textTLfont = {
									type = "text", name = L["Font"], desc = L["Sets the font"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textTLfont end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textTLfont = v
											bg:SetLayout()
										end,
									validate = LSM3_font,
									order = 102,
								}, -- <LSM3:font>
								textTLfontsize = {
									type = "range", name = L["Font Size"], desc = L["Sets the font size"],
									min = 4, max = 32, step = 1,
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textTLfontsize end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textTLfontsize = tonumber(v)
											bg:SetLayout()
										end,
									order = 102,
								}, -- <font size>
								textTLcolor = {
									type = "color", name = L["Font Color"], desc = L["Sets the font color"],
									get = function() return unpack(ElkBuffBars.db.profile.bargroups[id].bars.textTLcolor) end,
									set = function(r, g, b, a)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textTLcolor[1] = r
											bg.layout.bars.textTLcolor[2] = g
											bg.layout.bars.textTLcolor[3] = b
											bg.layout.bars.textTLcolor[4] = a
											bg:SetLayout()
										end,
									hasAlpha = true,
									order = 103,
								}, -- <color set>
								textTLalign = {
									type = "text", name = L["Alignment"], desc = L["Sets the text alignment (only if topleft text hidden)"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textTLalign end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textTLalign = v
											bg:SetLayout()
										end,
									validate = {"left", "center", "right"},
									order = 104
								}, -- left, center, right
							},
							order = 103,
						},
						texttr = {
							type = "group", name = L["Text topright"], desc = L["Settings for the topright text"], args = {
								textTR = {
									type = "text", name = L["Text shown"], desc = L["Sets the text which is shown"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textTR or "false" end,
									set = function(v)
											if v == "false" then v = false end
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textTR = v
											bg:SetLayout()
										end,
									validate = {["false"] = L["hide"], ["NAME"] = L["Name"], ["NAMERANK"] = L["Name, Rank"], ["NAMECOUNT"] = L["Name, Count"], ["NAMERANKCOUNT"] = L["Name, Rank, Count"], ["RANK"] = L["Rank"], ["COUNT"] = L["Count"], ["TIMELEFT"] = L["Time Left"], ["DEBUFFTYPE"] = L["Debuff Type"]},
									order = 101,
								}, -- false, "NAME", "NAMERANK", "NAMECOUNT", "NAMERANKCOUNT", "RANK", "COUNT", "TIMELEFT", "DEBUFFTYPE"
								textTRfont = {
									type = "text", name = L["Font"], desc = L["Sets the font"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textTRfont end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textTRfont = v
											bg:SetLayout()
										end,
									validate = LSM3_font,
									order = 102,
								}, -- <LSM3:font>
								textTRfontsize = {
									type = "range", name = L["Font Size"], desc = L["Sets the font size"],
									min = 4, max = 32, step = 1,
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textTRfontsize end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textTRfontsize = tonumber(v)
											bg:SetLayout()
										end,
									order = 103,
								}, -- <font size>
								textTRcolor = {
									type = "color", name = L["Font Color"], desc = L["Sets the font color"],
									get = function() return unpack(ElkBuffBars.db.profile.bargroups[id].bars.textTRcolor) end,
									set = function(r, g, b, a)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textTRcolor[1] = r
											bg.layout.bars.textTRcolor[2] = g
											bg.layout.bars.textTRcolor[3] = b
											bg.layout.bars.textTRcolor[4] = a
											bg:SetLayout()
										end,
									hasAlpha = true,
									order = 104,
								}, -- <color set>
							},
							order = 104,
						},
						textbl = {
							type = "group", name = L["Text bottomleft"], desc = L["Settings for the bottomleft text"], args = {
								textBL = {
									type = "text", name = L["Text shown"], desc = L["Sets the text which is shown"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textBL or "false" end,
									set = function(v)
											if v == "false" then v = false end
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textBL = v
											bg:SetLayout()
										end,
									validate = {["false"] = L["hide"], ["NAME"] = L["Name"], ["NAMERANK"] = L["Name, Rank"], ["NAMECOUNT"] = L["Name, Count"], ["NAMERANKCOUNT"] = L["Name, Rank, Count"], ["RANK"] = L["Rank"], ["COUNT"] = L["Count"], ["TIMELEFT"] = L["Time Left"], ["DEBUFFTYPE"] = L["Debuff Type"]},
									order = 101,
								}, -- false, "NAME", "NAMERANK", "NAMECOUNT", "NAMERANKCOUNT", "RANK", "COUNT", "TIMELEFT", "DEBUFFTYPE"
								textBLfont = {
									type = "text", name = L["Font"], desc = L["Sets the font"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textBLfont end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textBLfont = v
											bg:SetLayout()
										end,
									validate = LSM3_font,
									order = 102,
								}, -- <LSM3:font>
								textBLfontsize = {
									type = "range", name = L["Font Size"], desc = L["Sets the font size"],
									min = 4, max = 32, step = 1,
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textBLfontsize end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textBLfontsize = tonumber(v)
											bg:SetLayout()
										end,
									order = 103,
								}, -- <font size>
								textBLcolor = {
									type = "color", name = L["Font Color"], desc = L["Sets the font color"],
									get = function() return unpack(ElkBuffBars.db.profile.bargroups[id].bars.textBLcolor) end,
									set = function(r, g, b, a)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textBLcolor[1] = r
											bg.layout.bars.textBLcolor[2] = g
											bg.layout.bars.textBLcolor[3] = b
											bg.layout.bars.textBLcolor[4] = a
											bg:SetLayout()
										end,
									hasAlpha = true,
									order = 104,
								}, -- <color set>
								textBLalign = {
									type = "text", name = L["Alignment"], desc = L["Sets the text alignment (only if bottomleft text hidden)"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textBLalign end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textBLalign = v
											bg:SetLayout()
										end,
									validate = {"left", "center", "right"},
									order = 105,
								}, -- left, center, right
							},
							order = 105,
						},
						textbr = {
							type = "group", name = L["Text bottomright"], desc = L["Settings for the bottomright text"], args = {
								textBR = {
									type = "text", name = L["Text shown"], desc = L["Sets the text which is shown"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textBR or "false" end,
									set = function(v)
											if v == "false" then v = false end
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textBR = v
											bg:SetLayout()
										end,
									validate = {["false"] = L["hide"], ["NAME"] = L["Name"], ["NAMERANK"] = L["Name, Rank"], ["NAMECOUNT"] = L["Name, Count"], ["NAMERANKCOUNT"] = L["Name, Rank, Count"], ["RANK"] = L["Rank"], ["COUNT"] = L["Count"], ["TIMELEFT"] = L["Time Left"], ["DEBUFFTYPE"] = L["Debuff Type"]},
									order = 101,
								}, -- false, "NAME", "NAMERANK", "NAMECOUNT", "NAMERANKCOUNT", "RANK", "COUNT", "TIMELEFT", "DEBUFFTYPE"
								textBRfont = {
									type = "text", name = L["Font"], desc = L["Sets the font"],
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textBRfont end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textBRfont = v
											bg:SetLayout()
										end,
									validate = LSM3_font,
									order = 102,
								}, -- <LSM3:font>
								textBRfontsize = {
									type = "range", name = L["Font Size"], desc = L["Sets the font size"],
									min = 4, max = 32, step = 1,
									get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textBRfontsize end,
									set = function(v)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textBRfontsize = tonumber(v)
											bg:SetLayout()
										end,
									order = 103,
								}, -- <font size>
								textBRcolor = {
									type = "color", name = L["Font Color"], desc = L["Sets the font color"],
									get = function() return unpack(ElkBuffBars.db.profile.bargroups[id].bars.textBRcolor) end,
									set = function(r, g, b, a)
											local bg = ElkBuffBars.bargroups[id]
											bg.layout.bars.textBRcolor[1] = r
											bg.layout.bars.textBRcolor[2] = g
											bg.layout.bars.textBRcolor[3] = b
											bg.layout.bars.textBRcolor[4] = a
											bg:SetLayout()
										end,
									hasAlpha = true,
									order = 104,
								}, -- <color set>
							},
							order = 106,
						},
						abbreviate_name = {
							type = "range", name = L["Abbreviate Name"], desc = L["Abbreviate names longer than this (0 = disabled)"],
							min = 0, max = 100, step = 1,
							get = function() return ElkBuffBars.db.profile.bargroups[id].bars.abbreviate_name end,
							set = function(v)
									local bg = ElkBuffBars.bargroups[id]
									bg.layout.bars.abbreviate_name = tonumber(v)
									bg:UpdateText()
								end,
							order = 107,
						},
						timeformat = {
							type = "text", name = L["Time Format"], desc = L["Sets the format the time is shown in"],
							get = function() return ElkBuffBars.db.profile.bargroups[id].bars.timeformat end,
							set = function(v)
									local bg = ElkBuffBars.bargroups[id]
									bg.layout.bars.timeformat = v
									bg:UpdateTimeleft()
								end,
							validate = {"DEFAULT", "EXTENDED", "FULL", "SHORT", "CONDENSED"},
							order = 108,
						}, -- "DEFAULT", "EXTENDED", "FULL", "SHORT", "CONDENSED"
						padding = {
							type = "range", name = L["Padding"], desc = L["Sets the padding for the text strings"],
							min = 0, max = 10, step = 1,
							get = function() return ElkBuffBars.db.profile.bargroups[id].bars.padding end,
							set = function(v)
									local bg = ElkBuffBars.bargroups[id]
									bg.layout.bars.padding = tonumber(v)
									bg:SetLayout()
								end,
							order = 109,
						},
						tooltipanchor = {
							type = "text", name = L["Tooltip Anchor"], desc = L["Sets the anchor for tooltips"],
							get = function() return ElkBuffBars.db.profile.bargroups[id].bars.tooltipanchor end,
							set = function(v)
									local bg = ElkBuffBars.bargroups[id]
									bg.layout.bars.tooltipanchor = v
								end,
							validate = {"default", "ANCHOR_TOPRIGHT", "ANCHOR_RIGHT","ANCHOR_BOTTOMRIGHT", "ANCHOR_TOPLEFT", "ANCHOR_LEFT", "ANCHOR_BOTTOMLEFT", "ANCHOR_CURSOR", "ANCHOR_PRESERVE", "ANCHOR_NONE"},
							order = 110,
						},
						height = {
							type = "range", name = L["Height"], desc = L["Sets the bar hight"],
							min = 0, max = 100, step = 1,
							get = function() return ElkBuffBars.db.profile.bargroups[id].bars.height end,
							set = function(v)
									local bg = ElkBuffBars.bargroups[id]
									local blayout = bg.layout.bars
									blayout.height = tonumber(v)
									if blayout.height > blayout.width then blayout.height = blayout.width end
									bg:SetLayout()
									bg:UpdateBarPositions()
								end,
							order = 111,
						},
						width = {
							type = "range", name = L["Width"], desc = L["Sets the bar Width"],
							min = 0, max = 500, step = 1,
							get = function() return ElkBuffBars.db.profile.bargroups[id].bars.width end,
							set = function(v)
									local bg = ElkBuffBars.bargroups[id]
									local blayout = bg.layout.bars
									blayout.width = tonumber(v)
									if blayout.width < blayout.height then blayout.width = blayout.height end
									bg:SetLayout()
									if bg.layout.anchorshown then
										bg:ToggleAnchor(true)
									else
										bg:UpdateBarPositions()
									end
								end,
							order = 112,
						},
						alpha = {
							type = "range", name = L["Alpha"], desc = L["Sets the groups alpha value"],
							isPercent = true,
							get = function() return ElkBuffBars.db.profile.bargroups[id].bars.alpha end,
							set = function(v)
									local bg = ElkBuffBars.bargroups[id]
									bg.layout.bars.alpha = tonumber(v)
									bg:SetLayout()
								end,
							order = 113,
						},
					},
					order = 103,
				},
				barspacing = {
					type = "range", name = L["Bar Spacing"], desc = L["Sets gap between bars"],
					min = 0, max = 50, step = 1,
					get = function() return ElkBuffBars.db.profile.bargroups[id].barspacing end,
					set = function(v)
							local bg = ElkBuffBars.bargroups[id]
							bg.layout.barspacing = tonumber(v)
							bg:UpdateBarPositions()
						end,
					order = 104,
				},
				growup = {
					type = "toggle", name = L["Grow up"], desc = L["Toggles direction of buffs"],
					get = function() return ElkBuffBars.db.profile.bargroups[id].growup end,
					set = function(v)
							local bg = ElkBuffBars.bargroups[id]
							bg.layout.growup = v
							bg.layout.stickto = nil
							bg.layout.stickside = nil
							bg:SetLayout()
							bg:SetPosition()
						end,
					order = 105,
				},
				sorting = {
					type = "text", name = L["Sorting"], desc = L["Sets sorting of buffs"],
					get = function() return ElkBuffBars.db.profile.bargroups[id].sorting end,
					set = function(v)
							local bg = ElkBuffBars.bargroups[id]
							bg.layout.sorting = v
							bg:UpdateData()
						end,
					validate = {"name", "none", "timeleft", "timemax"},
					order = 106,
				},
				filter = {
					type = "group", name = L["Filter"], desc = L["Sets the buffs to show"], args = {
						type = {
							type = "text", name = L["Type"], desc = L["Sets which types of buffs to show"],
							get = function(k) return ElkBuffBars.db.profile.bargroups[id].filter.type[k] or false end,
							set = function(k, v)
									local bg = ElkBuffBars.bargroups[id]
									bg.layout.filter.type[k] = v or nil
									bg:UpdateData()
								end,
							multiToggle = true,
							validate = {"BUFF", "DEBUFF", "TENCH", "TRACKING"},
							order = 101,
						},
						untilcancelled = {
							type = "text", name = L["Timeless Buffs"], desc = L["Sets if and how to filter Timeless Buffs"],
							get = function() return ElkBuffBars.db.profile.bargroups[id].filter.untilcancelled or "none" end,
							set = function(v)
									local bg = ElkBuffBars.bargroups[id]
									if v == "none" then v = nil end
									bg.layout.filter.untilcancelled = v
									bg:UpdateData()
								end,
							validate = {only = L["whitelist"], none = L["don't filter"], hide = L["blacklist"]},
							order = 102,
						},
						timemax_min = {
							type = "text", name = L["Min. Timemax"], desc = L["Sets a minimum duration for buffs to show."], usage = L["time in seconds"],
							get = function() return ElkBuffBars.db.profile.bargroups[id].filter.timemax_min or "" end,
							set = function(v)
									v = tonumber(v)
									local bg = ElkBuffBars.bargroups[id]
									bg.layout.filter.timemax_min = (v ~= 0) and v or nil
									bg:UpdateData()
								end,
							order = 103,
						},
						timemax_max = {
							type = "text", name = L["Max. Timemax"], desc = L["Sets a maximum duration for buffs to show."], usage = L["time in seconds"],
							get = function() return ElkBuffBars.db.profile.bargroups[id].filter.timemax_max or "" end,
							set = function(v)
									v = tonumber(v)
									local bg = ElkBuffBars.bargroups[id]
									bg.layout.filter.timemax_max = (v ~= 0) and v or nil
									bg:UpdateData()
								end,
							order = 104,
						},
						names_include = {
							type = "group", name = L["White List"], desc = L["Only show buffs on white list (disabled if empty)"],
							args = {
								BUFF = {
									type = "text", name = "BUFF", desc = "BUFF",
									get = function(k)
											local ni = ElkBuffBars.db.profile.bargroups[id].filter.names_include
											return ni and ni.BUFF and ni.BUFF[k] or false
										end,
									set = function(name, value) SetNameFilter(id, true, "BUFF", name, value) end,
									multiToggle = true,
									validate = knownnames_validate.BUFF,
								},
								DEBUFF = {
									type = "text", name = "DEBUFF", desc = "DEBUFF",
									get = function(k)
											local ni = ElkBuffBars.db.profile.bargroups[id].filter.names_include
											return ni and ni.DEBUFF and ni.DEBUFF[k] or false
										end,
									set = function(name, value) SetNameFilter(id, true, "DEBUFF", name, value) end,
									multiToggle = true,
									validate = knownnames_validate.DEBUFF,
								},
								TENCH = {
									type = "text", name = "TENCH", desc = "TENCH",
									get = function(k)
											local ni = ElkBuffBars.db.profile.bargroups[id].filter.names_include
											return ni and ni.TENCH and ni.TENCH[k] or false
										end,
									set = function(name, value) SetNameFilter(id, true, "TENCH", name, value) end,
									multiToggle = true,
									validate = knownnames_validate.TENCH,
								},
								TRACKING = {
									type = "text", name = "TRACKING", desc = "TRACKING",
									get = function(k)
											local ni = ElkBuffBars.db.profile.bargroups[id].filter.names_include
											return ni and ni.TRACKING and ni.TRACKING[k] or false
										end,
									set = function(name, value) SetNameFilter(id, true, "TRACKING", name, value) end,
									multiToggle = true,
									validate = knownnames_validate.TRACKING,
								},
							},
							order = 105,
						},
						names_exclude = {
							type = "group", name = L["Black List"], desc = L["Don't show buffs on black list"],
							args = {
								BUFF = {
									type = "text", name = "BUFF", desc = "BUFF",
									get = function(k)
											local ne = ElkBuffBars.db.profile.bargroups[id].filter.names_exclude
											return ne and ne.BUFF and ne.BUFF[k] or false
										end,
									set = function(name, value) SetNameFilter(id, false, "BUFF", name, value) end,
									multiToggle = true,
									validate = knownnames_validate.BUFF,
								},
								DEBUFF = {
									type = "text", name = "DEBUFF", desc = "DEBUFF",
									get = function(k)
											local ne = ElkBuffBars.db.profile.bargroups[id].filter.names_exclude
											return ne and ne.DEBUFF and ne.DEBUFF[k] or false
										end,
									set = function(name, value) SetNameFilter(id, false, "DEBUFF", name, value) end,
									multiToggle = true,
									validate = knownnames_validate.DEBUFF,
								},
								TENCH = {
									type = "text", name = "TENCH", desc = "TENCH",
									get = function(k)
											local ne = ElkBuffBars.db.profile.bargroups[id].filter.names_exclude
											return ne and ne.TENCH and ne.TENCH[k] or false
										end,
									set = function(name, value) SetNameFilter(id, false, "TENCH", name, value) end,
									multiToggle = true,
									validate = knownnames_validate.TENCH,
								},
								TRACKING = {
									type = "text", name = "TRACKING", desc = "TRACKING",
									get = function(k)
											local ne = ElkBuffBars.db.profile.bargroups[id].filter.names_exclude
											return ne and ne.TRACKING and ne.TRACKING[k] or false
										end,
									set = function(name, value) SetNameFilter(id, false, "TRACKING", name, value) end,
									multiToggle = true,
									validate = knownnames_validate.TRACKING,
								},
							},
							order = 106,
						},
					},
					order = 107,
				},
				target = {
					type = "text", name = L["Target"], desc = L["Sets whos buffs to show"],
					get = function() return ElkBuffBars.db.profile.bargroups[id].target end,
					set = function(v)
							local bg = ElkBuffBars.bargroups[id]
							bg.layout.target = v
							bg:UpdateData()
						end,
					validate = {"focus", "pet", "player", "target"},
					order = 108,
				},
				clickthrough = {
					type = "toggle", name = L["Disable Mouse"], desc = L["Disable mouse input to allow click-through"],
					get = function() return ElkBuffBars.db.profile.bargroups[id].bars.clickthrough end,
					set = function(v)
							local bg = ElkBuffBars.bargroups[id]
							bg.layout.bars.clickthrough = v
							bg:SetLayout()
						end,
					order = 109,
				},
				copylayout = {
					type = "text", name = L["Copy Layout"], desc = L["Copys the layout from another bargroup"], usage = L["group id of the layout"],
					get = false,
					set = function(v)
							v = tonumber(v)
							if v ~= id and ElkBuffBars.bargroups[v] then
								ElkBuffBars:CopyBarLayout(ElkBuffBars.bargroups[id].layout, ElkBuffBars.bargroups[v].layout)
							end
						end,
					order = 110,
				},
				resetpos = {
					type = "execute", name = L["Reset Position"], desc = L["Resets the bargroup's position to screen center"],
					func = function()
							local bg = ElkBuffBars.bargroups[id]
							bg.layout.x = nil
							bg.layout.y = nil
							bg.stickto = nil
							bg.stickside = nil
							bg:SetPosition()
						end,
					order = 111,
				},
				remove = {
					type = "execute", name = L["Remove Group"], desc = L["Removes the bargroup"],
					func = function()
							Dewdrop:Close()
							ElkBuffBars:RemoveBarGroup(id)
						end,
					order = 112,
				},
			}
		}
	end
	return groupoptionscache[id]
end

function ElkBuffBars:ShowDewdrop()
	Dewdrop:Open(UIParent, "children", AO_allopts, "cursorX", true, "cursorY", true)
end

ElkBuffBars:RegisterChatCommand({"/ebb"}, {
	type = "group", args = {
		config = {
			type = "execute", name = "config", desc = L["Shows the config menu"],
			func = function() ElkBuffBars:ShowDewdrop() end,
		}
	}
})
ElkBuffBars.OnMenuRequest = AO_allopts