local core = LibStub("AceAddon-3.0"):GetAddon("SavedInstances")
local module = core:NewModule("Config")
local Config = LibStub("AceConfig-3.0")
local LDB = LibStub("LibDataBroker-1.1", true)
local icon = LDB and LibStub("LibDBIcon-1.0", true)
local L = LibStub("AceLocale-3.0"):GetLocale("SavedInstances")
local db, defaultDB

-- local (optimal) references to provided functions
local ipairs = ipairs
local pairs = pairs
local tinsert = tinsert
local tremove = tremove

-- local (optimal) references to Blizzard's strings
local COLOR = COLOR -- "Color"
local DEFAULTS = DEFAULTS -- "Defaults"
local DELETE = DELETE -- "DELETE"
local DUNGEON_DIFFICULTY1 = DUNGEON_DIFFICULTY1 -- 5 man
local DUNGEON_DIFFICULTY2 = DUNGEON_DIFFICULTY2 -- 5 man (Heroic)
local EMBLEM_SYMBOL = EMBLEM_SYMBOL -- "Icon"
local EXPANSION_NAME0 = EXPANSION_NAME0 -- "Classic"
local EXPANSION_NAME1 = EXPANSION_NAME1 -- "The Burning Crusade"
local EXPANSION_NAME2 = EXPANSION_NAME2 -- "Wrath of the Lich King"
local LFG_TYPE_DUNGEON = LFG_TYPE_DUNGEON -- "Dungeon"
local LFG_TYPE_RAID = LFG_TYPE_RAID -- "Raid"
local RAID_DIFFICULTY1 = RAID_DIFFICULTY1 -- "10 man"
local RAID_DIFFICULTY2 = RAID_DIFFICULTY2 -- "25 man"
local RAID_DIFFICULTY3 = RAID_DIFFICULTY3 -- "10 man (Heroic)"
local RAID_DIFFICULTY4 = RAID_DIFFICULTY4 -- "25 man (Heroic)"
local RESET_TO_DEFAULT = RESET_TO_DEFAULT -- "Reset to Default"
local FONTEND = FONT_COLOR_CODE_CLOSE
local GOLDFONT = NORMAL_FONT_COLOR_CODE
local Indicators = {
	ICON_STAR = ICON_LIST[1] .. "16:16:0:0|t",
	ICON_CIRCLE = ICON_LIST[2] .. "16:16:0:0|t",
	ICON_DIAMOND = ICON_LIST[3] .. "16:16:0:0|t",
	ICON_TRIANGLE = ICON_LIST[4] .. "16:16:0:0|t",
	ICON_MOON = ICON_LIST[5] .. "16:16:0:0|t",
	ICON_SQUARE = ICON_LIST[6] .. "16:16:0:0|t",
	ICON_CROSS = ICON_LIST[7] .. "16:16:0:0|t",
	ICON_SKULL = ICON_LIST[8] .. "16:16:0:0|t",
	BLANK = "None",
}

-- config global functions

function module:OnInitialize()
	db = core.db
	defaultDB = core.defaultDB
	module:SetupOptions()
end

-- general helper functions

local function TableLen(table)
	local i = 0
	for _, _ in pairs(table) do
		i = i + 1
	end
	return i
end

-- local addon functions below

local function InstanceCategory(instance)
	if not instance then return nil end
	local instance = db.Instances[instance]
	return ((instance.Raid and "R") or ((not instance.Raid) and "D")) .. instance.Expansion
end

local function InstancesInCategory(targetcategory)
	-- returns a table of the form { "instance1", "instance2", ... }
	if (not targetcategory) then return { } end
	local list = { }
	for instance, _ in pairs(db.Instances) do
		if InstanceCategory(instance) == targetcategory then
			list[#list+1] = instance
		end
	end
	return list
end

local function CategorySize(category)
	if not category then return nil end
	local i = 0
	for instance, _ in pairs(db.Instances) do
		if category == InstanceCategory(instance) then
			i = i + 1
		end
	end
	return i
end

local function OrderedInstances(category)
	-- returns a table of the form { "instance1", "instance2", ... }
	-- adjusts the Order value for each instance in the category
	if (not category) then return { } end
	local orderedlist = { }
	local instances = InstancesInCategory(category)
	while #orderedlist < CategorySize(category) and #instances > 0 do
		local nextinstance
		local nextinstanceindex
		for i, instance in ipairs(instances) do
			nextinstance = nextinstance or instance
			if db.Instances[instance].Order <= db.Instances[nextinstance].Order then
				nextinstance = instance
				nextinstanceindex = i
			end
		end
		orderedlist[#orderedlist+1] = nextinstance
		tremove(instances, nextinstanceindex)
	end
	for i, instance in ipairs(orderedlist) do
		db.Instances[instance].Order = i
	end
	return orderedlist
end

local function OrderedCategories()
	-- returns a table of the form { "instance1", "instance2", ... }
	-- adjusts the Order value for each category
	local orderedlist = { }
	local categories = { }
	for category, v in pairs(db.Categories) do
		categories[#categories+1] = category
	end
	while #orderedlist < TableLen(db.Categories) and #categories > 0 do
		local nextcategory
		local nextinstanceindex
		for i, category in ipairs(categories) do
			nextcategory = nextcategory or category
			if db.Categories[category].Order <= db.Categories[nextcategory].Order then
				nextcategory = category
				nextcategoryindex = i
			end
		end
		orderedlist[#orderedlist+1] = nextcategory
		tremove(categories, nextcategoryindex)
	end
	for i, category in ipairs(orderedlist) do
		db.Categories[category].Order = i
	end
	return orderedlist
end

local function ReorderInstance(category, from, to)
	-- modify the order of instances in their category given the starting and destination indices
	local instances = OrderedInstances(category)
	local movinginstance = instances[from]
	tremove(instances, from)
	tinsert(instances, to, movinginstance)
	for i, instance in ipairs(instances) do
		db.Instances[instance].Order = i
	end
end

local function ReorderCategory(from, to)
	-- modify the order of categories given the starting and destination indices
	local categories = OrderedCategories()
	local movingcategory = categories[from]
	tremove(categories, from)
	tinsert(categories, to, movingcategory)
	for i, category in ipairs(categories) do
		db.Categories[category].Order = i
	end
end

-- options functions below

local function IndicatorIconOptions(nextorder)
	return { order = nextorder, type = "select", width = "half", name = EMBLEM_SYMBOL, values = Indicators }
end

local function IndicatorTextOptions(nextorder)
	return { order = nextorder, type = "input", name = L["Text"], multiline = false }
end

local function IndicatorColorOptions(nextorder, indicatortype)
	return { order = nextorder, type = "color", width = "half", hasAlpha = false, name = COLOR,
		disabled = function()
			return db.Indicators[indicatortype .. "ClassColor"]
		end,
		get = function(info)
			local r = db.Indicators[info[#info]][1]
			local g = db.Indicators[info[#info]][2]
			local b = db.Indicators[info[#info]][3]
			return r, g, b, nil
		end,
		set = function(info, r, g, b, ...)
			db.Indicators[info[#info]][1] = r
			db.Indicators[info[#info]][2] = g
			db.Indicators[info[#info]][3] = b
		end,
	}
end

local function IndicatorClassColorOption(nextorder)
	return { order = nextorder, type = "toggle", name = L["Use class color"] }
end

local function GroupListGUI(order, name, list)
	local total = TableLen(list)
	local group = {
		type = "group",
		inline = true,
		name = name,
		order = order,
		args = {
			item1 = {
				type = "description",
				name = L["List is empty"],
			},
		},
	}
	for i = 1, total do
		group.args["item" .. i] = {
			type = "description",
			name = list[i],
			order = i,
		}
	end
	return group
end

local function GenerateCategoriesListGUI(order)
	local catoptions = core.Options.args.Categories.args.OrderGroup.args
	local list = { }
	for i, v in ipairs(OrderedCategories()) do
		local item = db.Categories[v].Name
		if module.selectedCategory and module.selectedCategory == v then
			item = GOLDFONT .. item .. FONTEND
		end
		list[#list+1] = item
	end
	if catoptions.CategoryList then
		catoptions.CategoryList = nil
	end
	catoptions.CategoryList = GroupListGUI(order, L["Categories"], list)
end

local function GenerateInstancesListGUI(order)
	local instoptions = core.Options.args.Instances.args.OrderGroup.args
	if not module.selectedCategory then
		instoptions.InstanceList = GroupListGUI(order, L["Instances"], { })
		return
	end
	local list = { }
	for i, v in ipairs(OrderedInstances(module.selectedCategory)) do
		local item = v
		if module.selectedInstance and module.selectedInstance == v then
			item = GOLDFONT .. item .. FONTEND
		end
		list[#list+1] = item
	end
	if instoptions.InstanceList then
		instoptions.InstanceList = nil
	end
	instoptions.InstanceList = GroupListGUI(order, L["Instances"], list)	
end

local function GenerateEncountersListGUI(order)
	local encoptions = core.Options.args.Instances.args.EncountersGroup.args
	if not module.selectedCategory or not module.selectedInstance 
			or not db.Instances[module.selectedInstance].Encounters then
		encoptions.EncountersList = GroupListGUI(order, L["Encounters"], { })
		return
	end
	local list = { }
	for i, v in ipairs(db.Instances[module.selectedInstance].Encounters) do
		local item = v
		if module.selectedEncounter and module.selectedEncounter == i then
			item = GOLDFONT .. item .. FONTEND
		end
		list[#list+1] = item
	end
	if encoptions.EncountersList then
		encoptions.EncountersList = nil
	end
	encoptions.EncountersList = GroupListGUI(order, L["Encounters"], list)	
end

-- options table below

core.Options = {
	type = "group",
	name = "SavedInstances",
	handler = SavedInstances,
	args = {
		General = {
			order = 1,
			type = "group",
			name = L["General settings"],
			get = function(info)
					return db.Tooltip[info[#info]]
			end,
			set = function(info, value)
					db.Tooltip[info[#info]] = value
			end,
			args = {
				intro = {
					order = 1,
					type = "description",
					name = L["Track the instance IDs saved against your characters"],
				},
				GeneralHeader = {
					order = 2, 
					type = "header",
					name = L["General settings"],
				},
				MinimapIcon = {
					type = "toggle",
					name = L["Show minimap button"],
					desc = L["Show the SavedInstances minimap button"],
					order = 3,
					hidden = function() return not icon end,
					get = function(info) return not db.MinimapIcon.hide end,
					set = function(info, value)
						db.MinimapIcon.hide = not value
						if value then icon:Show("SavedInstances") else icon:Hide("SavedInstances") end
					end,
				},
				ShowHints = {
					type = "toggle",
					name = L["Show tooltip hints"],
					width = "full",
					order = 4,
				},
				
				CategoriesHeader = {
					order = 11, 
					type = "header",
					name = L["Categories"],
				},
				ShowCategories = {
					type = "toggle",
					name = L["Show category names"],
					desc = L["Show category names in the tooltip"],
					order = 12,
				},
				ShowSoloCategory = {
					type = "toggle",
					name = L["Single category name"],
					desc = L["Show name for a category when all displayed instances belong only to that category"],
					order = 13,
					disabled = function()
						return not db.Tooltip.ShowCategories
					end,
				},
				
				InstancesHeader = {
					order = 20, 
					type = "header",
					name = L["Instances"],
				},
				NewInstanceShow = {
					type = "toggle",
					width = "full",
					order = 21,
					name = L["Always show new instances"],
					desc = L["New instances are shown by default, even if no characters are saved to them"],
				},
				ShowEncounters = {
					type = "toggle",
					width = "full",
					order = 22,
					name = L["Show encounters"],
					desc = L["If encounters have been defined, show them in the instance tooltip"],
				},
				
				ToonHeader = {
					order = 31, 
					type = "header",
					name = L["Characters"],
					hidden = true,
				},
				ColumnStyle = {
					order = 32,
					type = "select",
					width = "double",
					style = "radio",
					hidden = true,
					disabled = true,
					name = L["Character column style"],
					values = {
						["ALTERNATING"] = L["Alternating columns are colored differently"],
						["CLASS"] = L["Columns are colored according to the characters class"],
						["NORMAL"] = L["Columns are the same color as the whole tooltip"],
					},
				},
				AltColumnColor = { 
					order = 33,
					type = "color",
					width = "half",
					hasAlpha = true,
					name = COLOR,
					hidden = true,
--					hidden = function()
--						return not (db.Tooltip.ColumnStyle == "ALTERNATING")
--					end,
					disabled = true,
--					disabled = function()
--						return not (db.Tooltip.ColumnStyle == "ALTERNATING")
--					end,
					get = function(info)
						local r = db.Tooltip[info[#info]][1]
						local g = db.Tooltip[info[#info]][2]
						local b = db.Tooltip[info[#info]][3]
						local a = db.Tooltip[info[#info]][4]
						return r, g, b, a
					end,
					set = function(info, r, g, b, a)
						db.Tooltip[info[#info]][1] = r
						db.Tooltip[info[#info]][2] = g
						db.Tooltip[info[#info]][3] = b
						db.Tooltip[info[#info]][4] = a
					end,
				},
				
				HistoryHeader = {
					order = 41, 
					type = "header",
					hidden = true,
					name = L["Recent instance activity"],
				},
				HistoryHelp = {
					order = 42,
					type = "description",
					hidden = true,
					name = L["Blizzard currently imposes a limit of 5 instances per hour per account. This feature will show you how many different instances you have entered in the last hour (if you have been in more than two). Once you have reached the limit, you will be shown how much time you must wait until you will be allowed to enter a new instance."],
				},
				BrokerHistory = {
					type = "toggle",
					hidden = true,
					width = "full",
					name = L["Show history in Broker data feed"],
					order = 43,
					get = function(info) return db.Broker.HistoryText end,
					set = function(info, value)
						db.Broker.HistoryText = value
						UpdateLDBTextMode()
					end,
				},
				RecentHistory = {
					type = "toggle",
					hidden = true,
					width = "full",
					name = L["Show history in tooltip"],
					order = 44,
				},
				
				DefaultsHeader = {
					order = -2, 
					type = "header",
					name = DEFAULTS,
				},
				ResetButton = {
					order = -1,
					type = "execute",
					name = RESET_TO_DEFAULT,
					func = function()
						db.Tooltip = core.defaultDB.Tooltip
						db.Broker = core.defaultDB.Broker
					end,
				},

			},
		},
		Indicators = {
			order = 2,
			type = "group",
			name = L["Indicators"],
			get = function(info)
					return db.Indicators[info[#info]]
			end,
			set = function(info, value)
					db.Indicators[info[#info]] = value
			end,
			args = {
				Instructions = {
					order = 1,
					type = "description",
					name = L["You can combine icons and text in a single indicator if you wish. Simply choose an icon, and insert the word ICON into the text field. Anywhere the word ICON is found, the icon you chose will be substituted in."],
				},

				D1 = {
					type = "group",
					name = DUNGEON_DIFFICULTY1,
					order = 2,
					args = {
						D1Indicator = IndicatorIconOptions(1),
						D1Text = IndicatorTextOptions(2),
						D1Color = IndicatorColorOptions(3, "D1"),
						D1ClassColor = IndicatorClassColorOption(4),
					},
				},	
				
				D2 = {
					type = "group",
					name = DUNGEON_DIFFICULTY2,
					order = 3,
					args = {
						D2Indicator = IndicatorIconOptions(1),
						D2Text = IndicatorTextOptions(2),
						D2Color = IndicatorColorOptions(3, "D2"),
						D2ClassColor = IndicatorClassColorOption(4),
					},
				},
				
				R1 = {
					type = "group",
					order = 4,
					name = RAID_DIFFICULTY1,
					args = {
						R1Indicator = IndicatorIconOptions(1),
						R1Text = IndicatorTextOptions(2),
						R1Color = IndicatorColorOptions(3, "R1"),
						R1ClassColor = IndicatorClassColorOption(4),
					},
				},

				R2 = {
					type = "group",
					order = 5,
					name = RAID_DIFFICULTY2,
					args = {
						R2Indicator = IndicatorIconOptions(1),
						R2Text = IndicatorTextOptions(2),
						R2Color = IndicatorColorOptions(3, "R2"),
						R2ClassColor = IndicatorClassColorOption(4),
					},
				},
				
				R3 = {
					type = "group",
					order = 6,
					name = RAID_DIFFICULTY3,
					args = {
						R3Indicator = IndicatorIconOptions(1),
						R3Text = IndicatorTextOptions(2),
						R3Color = IndicatorColorOptions(3, "R3"),
						R3ClassColor = IndicatorClassColorOption(4),
					},
				},

				R4 = {
					type = "group",
					order = 7,
					name = RAID_DIFFICULTY4,
					args = {
						R4Indicator = IndicatorIconOptions(1),
						R4Text = IndicatorTextOptions(2),
						R4Color = IndicatorColorOptions(3, "R4"),
						R4ClassColor = IndicatorClassColorOption(4),
					},
				},

				ResetButton = {
					order = -1,
					type = "execute",
					name = RESET_TO_DEFAULT,
					func = function()
						db.Indicators = defaultDB.Indicators
					end,
				},
			},
		},
		Categories = {
			order = 3,
			type = "group",
			name = L["Categories"],
			childGroups = "tab",
			args = {
				SelectedCategory = {
					order = 1,
					type = "select",
					width = "full",
					name = L["Selected category"],
					disabled = false,
					get = function(info, category)
						if not module.selectedCategory then return end
						return db.Categories[module.selectedCategory].Order
					end,
					set = function(info, index)
						local categories = OrderedCategories()
						module.selectedCategory = categories[index]
						module.selectedInstance = nil
						module.selectedEncounter = nil
						GenerateCategoriesListGUI(3)
						GenerateInstancesListGUI(3)
					end,
					values = function()
						local table = { }
						for i, v in ipairs(OrderedCategories()) do
							table[i] = db.Categories[v].Name
						end
						return table
					end,
				},
				OrderGroup = {
					type = "group",
					inline = true,
					name = L["Category order"],
					order = 2,
					args = {
						MoveUp = {
							type = "execute",
							order = 1,
							name = L["Move up"],
							disabled = function()
								return not module.selectedCategory or db.Categories[module.selectedCategory].Order == 1
							end,
							func = function()
								local order = db.Categories[module.selectedCategory].Order
								ReorderCategory(order, order - 1)
								GenerateCategoriesListGUI(3)
							end,
						},
						MoveDown = {
							type = "execute",
							order = 2,
							name = L["Move down"],
							disabled = function()
								return not module.selectedCategory or db.Categories[module.selectedCategory].Order == TableLen(db.Categories)
							end,
							func = function()
								local order = db.Categories[module.selectedCategory].Order
								ReorderCategory(order, order + 1)
								GenerateCategoriesListGUI(3)
							end,
						},
					},
				},
				ResetButton = {
					order = -1,
					type = "execute",
					name = RESET_TO_DEFAULT,
					func = function()
						db.Categories = defaultDB.Categories
						GenerateCategoriesListGUI(3)
					end,
				},
			},
		},
		Instances = {
			order = 4,
			type = "group",
			name = L["Instance options"],
			childGroups = "tab",
			args = {
				SelectedCategory = {
					order = 1,
					type = "select",
					name = L["Selected category"],
					disabled = false,
					get = function(info, category)
						if not module.selectedCategory then return end
						return db.Categories[module.selectedCategory].Order
					end,
					set = function(info, index)
						local categories = OrderedCategories()
						module.selectedCategory = categories[index]
						module.selectedInstance = nil
						module.selectedEncounter = nil
						GenerateInstancesListGUI(3)
						GenerateEncountersListGUI(3)
					end,
					values = function()
						local table = { }
						for i, v in ipairs(OrderedCategories()) do
							table[i] = db.Categories[v].Name
						end
						return table
					end,
				},
				SelectedInstance = {
					order = 2,
					type = "select",
					name = L["Selected instance"],
					disabled = function()
						return (module.selectedCategory == nil) or
							(TableLen(OrderedInstances(module.selectedCategory)) == 0)
					end,
					get = function(info, order)
						if module.selectedInstance == nil then return end
						return db.Instances[module.selectedInstance].Order
					end,
					set = function(info, index)
						for instance, v in pairs(db.Instances) do
							if (InstanceCategory(instance) == module.selectedCategory) and (v.Order == index) then
								module.selectedInstance = instance
								module.selectedEncounter = nil
								GenerateInstancesListGUI(3)
								GenerateEncountersListGUI(3)
								break
							end
						end
					end,
					values = function()
						if module.selectedCategory == nil then return { } end
						local table = { }
						for i, name in ipairs(OrderedInstances(module.selectedCategory)) do
							table[i] = name
						end
						return table
					end,
				},

				OrderGroup = {
					order = 3, 
					type = "group",
					name = L["Instance order"],
					args = {
						MoveUp = {
							type = "execute",
							order = 1,
							name = L["Move up"],
							disabled = function()
								return not module.selectedCategory or not module.selectedInstance or db.Instances[module.selectedInstance].Order == 1
							end,
							func = function()
								local category = InstanceCategory(module.selectedInstance)
								local order = db.Instances[module.selectedInstance].Order
								ReorderInstance(category, order, order - 1)
								GenerateInstancesListGUI(3)
							end,
						},
						MoveDown = {
							type = "execute",
							order = 2,
							name = L["Move down"],
							disabled = function()
								return not module.selectedCategory or not module.selectedInstance or db.Instances[module.selectedInstance].Order == CategorySize(module.selectedCategory)
							end,
							func = function()
								local category = InstanceCategory(module.selectedInstance)
								local order = db.Instances[module.selectedInstance].Order
								ReorderInstance(category, order, order + 1)
								GenerateInstancesListGUI(3)
							end,
						},
					},
				},

				DetailsGroup = {
					order = 4, 
					type = "group",
					name = L["Instance details"],
					disabled = function()
						return not module.selectedInstance or (InstanceCategory(module.selectedInstance) ~= module.selectedCategory)
					end,
					args = {
						Expansion = {
							order = 1,
							type = "select",
							name = L["Expansion"],
							get = function(info)
								if module.selectedInstance then
									return db.Instances[module.selectedInstance].Expansion
								end
							end,
							set = function(info, expansion)
								local instance = db.Instances[module.selectedInstance]
								instance.Expansion = expansion
								instance.Raid = instance.Raid or false
								module.selectedCategory = InstanceCategory(module.selectedInstance)
							end,
							values = {
								[0] = EXPANSION_NAME0,
								[1] = EXPANSION_NAME1,
								[2] = EXPANSION_NAME2,
							},
						},
						Raid = {
							order = 2,
							type = "toggle",
							width = "full",
							name = LFG_TYPE_RAID,
							get = function(info)
								if module.selectedInstance then
									return db.Instances[module.selectedInstance].Raid
								end
							end,
							set = function(info, value)
								db.Instances[module.selectedInstance].Raid = value
								module.selectedCategory = InstanceCategory(module.selectedInstance)
							end,
						},
						AlwaysShow = {
							order = 3,
							type = "toggle",
							width = "full",
							name = L["Show when not saved"],
							get = function(info)
								if module.selectedInstance then
									return db.Instances[module.selectedInstance].Show
								end
							end,
							set = function(info, value)
								db.Instances[module.selectedInstance].Show = value
							end,
						},
						DeleteButton = {
							order = -1,
							type = "execute",
							name = DELETE,
							func = function()
								local instance = module.selectedInstance
								module.selectedInstance = nil
								db.Instances[instance] = nil
							end,
						},
					},
				},
				
				EncountersGroup = {
					order = 5, 
					type = "group",
					name = L["Encounters"],
					disabled = function()
						return not module.selectedInstance
					end,
					args = {
						EncounterName = {
							order = 1,
							type = "input",
							width = "double",
							name = L["New encounter"],
							get = nil,
							set = function(info, value)
								db.Instances[module.selectedInstance].Encounters = db.Instances[module.selectedInstance].Encounters or { }
								local encounters = db.Instances[module.selectedInstance].Encounters
								encounters[#encounters+1] = value
								module.selectedEncounter = TableLen(encounters)
								GenerateEncountersListGUI(3)
							end,
						},
						SelectedEncounter = {
							order = 2,
							type = "select",
							width = "double",
							name = L["Selected encounter"],
							get = function(info)
								return module.selectedEncounter
							end,
							set = function(info, value)
								module.selectedEncounter = value
								GenerateEncountersListGUI(3)
							end,
							values = function()
								db.Instances[module.selectedInstance].Encounters = db.Instances[module.selectedInstance].Encounters or { }
								local encounters = db.Instances[module.selectedInstance].Encounters
								local table = { }
								for i, v in ipairs(encounters) do
									table[i] = v
								end
								return table
							end,
						},
						DeleteButton = {
							order = -1,
							type = "execute",
							name = DELETE,
							disabled = function()
								return not module.selectedInstance or not module.selectedEncounter
							end,
							func = function()
								local encounter = module.selectedEncounter
								module.selectedEncounter = nil
								tremove(db.Instances[module.selectedInstance].Encounters, encounter)
								GenerateEncountersListGUI(3)
							end,
						},
					},
				},
			},
		},
		Characters = {
			order = 4,
			type = "group",
			name = L["Characters"],
			childGroups = "tab",
			disabled = function()
				return module.selectedToon == nil
			end,
			args = {
				SelectedToon = {
					order = 1,
					type = "select",
					width = "double",
					name = L["Selected character"],
					disabled = false,
					get = function(info, toon)
						return module.selectedToon
					end,
					set = function(info, toon)
						local categories = OrderedCategories()
						module.selectedToon = toon
					end,
					values = function()
						local table = { }
						for toon, t in pairs(db.Toons) do
							table[toon] = toon
						end
						return table
					end,
				},
				
				DetailsGroup = {
					order = 2, 
					type = "group",
					name = L["Character details"],
					args = {
						AlwaysShow = {
							order = 1,
							type = "toggle",
							width = "full",
							name = L["Show when not saved"],
							get = function(info)
								if module.selectedToon then
									return db.Toons[module.selectedToon].AlwaysShow
								end
							end,
							set = function(info, value)
								db.Toons[module.selectedToon].AlwaysShow = value
							end,
						},
						DeleteButton = {
							order = 4,
							type = "execute",
							name = DELETE,
							func = function()
								local toon = module.selectedToon
								module.selectedToon = nil
								db.Toons[toon] = nil
							end,
						},
					},
				},
			},
		},
		Lockouts = {
			order = 5,
			type = "group",
			childGroups = "tab",
			name = L["Lockouts"],
			disabled = function()
				return module.selectedLockout == nil
			end,
			args = {
				SelectedToon = {
					order = 1,
					type = "select",
					width = "double",
					name = L["Selected lockout"],
					disabled = function()
						return TableLen(db.Lockouts) == 0
					end,
					get = function(info)
						return module.selectedLockout
					end,
					set = function(info, value)
						module.selectedLockout = value
					end,
					values = function()
						local table = { }
						for lockout, l in pairs(db.Lockouts) do
							table[lockout] = lockout .. " " .. l.Name
						end
						return table
					end,
				},
				LockoutNote = {
					order = 2,
					type = "input",
					width = "double",
					name = L["Note"],
					get = function()
						if not module.selectedLockout then return end
						return db.Lockouts[module.selectedLockout].Note
					end,
					set = function(info, value)
						db.Lockouts[module.selectedLockout].Note = value
					end,
				},
				EncountersGroup = {
					order = 3, 
					type = "group",
					name = L["Encounters"],
					args = {
						Completed = {
							order = 1,
							type = "multiselect",
--							width = "double",
							name = L["Completed encounters"],
							get = function(info, key)
								return db.Lockouts[module.selectedLockout].Encounters[key]
							end,
							set = function(info, key, value)
								db.Lockouts[module.selectedLockout].Encounters[key] = value
							end,
							values = function()
								return db.Instances[db.Lockouts[module.selectedLockout].Name].Encounters
							end,
						},
					},
				},
				MembersGroup = {
					order = 4, 
					type = "group",
					name = L["Members"],
					hidden = true,
					args = {
					},
				},
			},
		},
	},
}

-- global functions

local lockoutgroup
--function module:ShowLockoutWindow(lockout)
--	print(tostring(lockout))
--	module.selectedLockout = arg
--	InterfaceOptionsFrame_OpenToCategory(lockoutgroup)
--end

local firstoptiongroup, lastoptiongroup
function module:SetupOptions()
	GenerateCategoriesListGUI(3)
	GenerateInstancesListGUI(3)
	local ACD = LibStub("AceConfigDialog-3.0")
	local namespace = "SavedInstances"
	LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable(namespace, core.Options)
	firstoptiongroup = ACD:AddToBlizOptions(namespace, nil, nil, "General")
	ACD:AddToBlizOptions(namespace, L["Indicators"], namespace, "Indicators")
	ACD:AddToBlizOptions(namespace, L["Categories"], namespace, "Categories")
	ACD:AddToBlizOptions(namespace, L["Instances"], namespace, "Instances")
	ACD:AddToBlizOptions(namespace, L["Characters"], namespace, "Characters")
	lockoutgroup = ACD:AddToBlizOptions(namespace, L["Lockouts"], namespace, "Lockouts")
	lastoptiongroup = lockoutgroup
end

function module:ShowConfig()
	InterfaceOptionsFrame_OpenToCategory(lastoptiongroup)
	InterfaceOptionsFrame_OpenToCategory(firstoptiongroup)
end

