-- global functions
local pairs = pairs
local type = type

local L = Gladius.L

Gladius.defaults = {
	profile = {
		x = { },
		y = { },
		modules = {
			["*"] = true,
			["Auras"] = false,
			["TargetBar"] = false,
		},
		locked = false,
		growUp = false,
		growRight = false,
		growLeft = false,
		groupButtons = true,
		advancedOptions = false,
		backgroundColor = {r = 0, g = 0, b = 0, a = 0.4},
		backgroundPadding = 5,
		bottomMargin = 20,
		useGlobalFontSize = true,
		globalFontSize = 11,
		globalFont = "Friz Quadrata TT",
		barWidth = 160,
		frameScale = 1,
	},
}

local function pairsByKeys(t, f)
	local a = { }
	for n in pairs(t) do table.insert(a, n) end
	table.sort(a, f)
	local i = 0 -- iterator variable
	local iter = function () -- iterator function
		i = i + 1
		if a[i] == nil then
			return nil
		else
			return a[i], t[a[i]]
		end
	end
	return iter
end

function Gladius:SetTemplate(template)
	if (template == 1) then
		-- classic Gladius1 template
		print("Gladius:", "Template not available!")
	elseif (template == 2) then
		-- reset to default
		Gladius.dbi:ResetProfile()
	else
		-- enable all features
		print("Gladius:", "Template not available!")
	end
end

SLASH_GLADIUS1 = "/gladius"
SlashCmdList["GLADIUS"] = function(msg)
	if (msg:find("test") and not Gladius.test) then
		if Gladius.instanceType ~= "arena" then
			local test
			if (msg == "test2") then
				test = 2
			elseif (msg == "test3") then
				test = 3
			elseif (msg == "test5") then
				test = 5
			else
				test = tonumber(msg:match("^test (.+)"))
				if (not test or test > 5 or test < 2 or test == 4) then
					test = 5
				end
			end
			Gladius.testCount = test
			Gladius.test = true
			Gladius:HideFrame()
			-- create and update buttons on first launch
			for i = 1, test do
				if (not Gladius.buttons["arena"..i]) then
					Gladius:UpdateUnit("arena"..i)
				end
				if (Gladius.buttons["arena"..i]) then
					Gladius.buttons["arena"..i]:RegisterForDrag("LeftButton")
					Gladius.buttons["arena"..i]:Show()
				end
			end
			-- update buttons, so every module should be fine
			Gladius:UpdateFrame()
		else
			Gladius:Print(L["You can't use this function inside arenas."])
		end
	elseif (msg == "" or msg == "options" or msg == "config" or msg == "ui") then
		AceDialog = AceDialog or LibStub("AceConfigDialog-3.0")
		AceRegistry = AceRegistry or LibStub("AceConfigRegistry-3.0")
		if (not Gladius.options) then
			Gladius:SetupOptions()
			AceDialog:SetDefaultSize("Gladius", 830, 530)
		end
		AceDialog:Open("Gladius")
	elseif (msg == "hide" or (msg:find("test") and Gladius.test)) then
		-- reset test environment
		Gladius.testCount = 0
		Gladius.test = false
		for i = 1, 5 do
			if (Gladius.buttons["arena"..i]) then
				Gladius.buttons["arena"..i]:RegisterForDrag()
				Gladius.buttons["arena"..i]:Hide()
			end
		end
		-- hide buttons
		Gladius:HideFrame()
	elseif (msg == "reset") then
		-- reset profile
		Gladius.dbi:ResetProfile()
	end
end

local function getOption(info)
	return (info.arg and Gladius.dbi.profile[info.arg] or Gladius.dbi.profile[info[#info]])
end

local function setOption(info, value)
	local key = info[#info]
	Gladius.dbi.profile[key] = value
	info = info.arg and info.arg or info[1]
	if (info == "general") then
		Gladius:UpdateFrame()
	else
		Gladius:UpdateFrame(info)
	end
end

function Gladius:GetColorOption(info)
	local key = info.arg or info[#info]
	return self.dbi.profile[key].r, self.dbi.profile[key].g, self.dbi.profile[key].b, self.dbi.profile[key].a
end

function Gladius:SetColorOption(info, r, g, b, a)
	local key = info.arg or info[#info]
	self.dbi.profile[key].r, self.dbi.profile[key].g, self.dbi.profile[key].b, self.dbi.profile[key].a = r, g, b, a
	if (info[1] == "general") then
		Gladius:UpdateFrame()
	else
		Gladius:UpdateFrame(info[1])
	end
end

function Gladius:GetPositions()
	return {
		["TOPLEFT"] = L["Top Left"],
		["TOPRIGHT"] = L["Top Right"],
		["LEFT"] = L["Center Left"],
		["RIGHT"] = L["Center Right"],
		["BOTTOMLEFT"] = L["Bottom Left"],
		["BOTTOMRIGHT"] = L["Bottom Right"],
	}
end

function Gladius:SetupModule(key, module, order)
	self.options.args[key] = {
		type = "group",
		name = L[key],
		desc = L[key.." settings"],
		childGroups = "tab",
		order =order,
		args = { },
	}
	-- set additional module options
	local options = module:GetOptions()
	if (type(options) == "table") then
		self.options.args[key].args = options
	end
	-- set enable module option
	self.options.args[key].args.enable = {
		type = "toggle",
		name = L["Enable Module"],
		set=function(info, v)
			local module = info[1]
			self.dbi.profile.modules[module] = v
			if (v) then
				self:EnableModule(module)
				-- evil haxx
				self:Call(self.modules[module], "OnEnable")
			else
				self:DisableModule(module)
				-- evil haxx
				self:Call(self.modules[module], "OnDisable")
			end
			self:UpdateFrame()
		end,
		get=function(info)
			local module = info[1]
			return self.dbi.profile.modules[module]
		end,
		order = 0,
	}
	-- set reset module option
	self.options.args[key].args.reset = {
		type = "execute",
		name = L["Reset Module"],
		func = function()
			for k,v in pairs(module.defaults) do
				self.dbi.profile[k] = v
			end
			Gladius:UpdateFrame()
		end,
		order = 0.5,
	}
end

function Gladius:SetupOptions()
	self.options = {
		type = "group",
		name = "Gladius "..GetAddOnMetadata("Gladius", "Version"),
		plugins = { },
		get = getOption,
		set = setOption,
		args = {
			general = {
				type = "group",
				name = L["General"],
				desc = L["General settings"],
				order = 1,
				args = {
					general = {
						type = "group",
						name = L["General"],
						desc = L["General settings"],
						inline = true,
						order = 1,
						args = {
							locked = {
								type = "toggle",
								name = L["Lock frame"],
								desc = L["Toggle if the frame can be moved"],
								order = 1,
							},
							growT = {
								order = 5,
								type = "select",
								name = "Direction",
								desc = L["The Direction you want the frame to go in."],
								values = {
									[1] = "Up",
									[2] = "Down",
									[3] = "Left",
									[4] = "Right"
								},
								get = function()
									return growT
								end,
								set = function(info, value)
									if(value == 1)then
										self.dbi.profile.growUp = true
										self.dbi.profile.growLeft = false
										self.dbi.profile.growRight = false
									end
									if(value == 2)then
										self.dbi.profile.growUp = false
										self.dbi.profile.growLeft = false
										self.dbi.profile.growRight = false
									end
									if(value == 3)then
										self.dbi.profile.growUp = false
										self.dbi.profile.growLeft = true
										self.dbi.profile.growRight = false
									end
									if(value == 4)then
										self.dbi.profile.growUp = false
										self.dbi.profile.growLeft = false
										self.dbi.profile.growRight = true
									end
									growT = value
								end,
							},
							sep = {
								type = "description",
								name = "",
								width = "full",
								order = 7,
							}, 
							groupButtons = {
								type = "toggle",
								name = L["Group Buttons"],
								desc = L["If this is toggle buttons can be moved separately"],
								order = 10,
							},
							advancedOptions = {
								type = "toggle",
								name = L["Advanced Options"],
								desc = L["Toggle advanced options"],
								order = 15,
							},
						},
					},
					frame = {
						type = "group",
						name = L["Frame"],
						desc = L["Frame settings"],
						inline = true,
						order = 2,
						args = {
							backgroundColor = {
								type = "color",
								name = L["Background Color"],
								desc = L["Color of the frame background"],
								hasAlpha = true,
								get = function(info)
									return Gladius:GetColorOption(info)
								end,
								set = function(info, r, g, b, a)
									return Gladius:SetColorOption(info, r, g, b, a)
								end,
								disabled = function()
									return not self.dbi.profile.groupButtons
								end,
								order = 1,
							},
							backgroundPadding = {
								type = "range",
								name = L["Background Padding"],
								desc = L["Padding of the background"],
								min = 0, max = 100, step = 1,
								disabled = function()
									return not self.dbi.profile.groupButtons
								end,
								order = 5,
							},
							sep = {
								type = "description",
								name = "",
								width = "full",
								order = 7,
							},
							bottomMargin = {
								type = "range",
								name = L["Bottom Margin"],
								desc = L["Margin between each button"],
								min = 0, max = 300, step = 1,
								disabled = function()
									return not self.dbi.profile.groupButtons
								end,
								width = "double",
								order = 10,
							},
						},
					},
					size = {
						type = "group",
						name = L["Size"],
						desc = L["Size settings"],
						inline = true,
						order = 3,
						args = {
							barWidth = {
								type = "range",
								name = L["Bar width"],
								desc = L["Width of the module bars"],
								min = 10, max = 500, step = 1,
								order = 1,
							},
							frameScale = {
								type = "range",
								name = L["Frame scale"],
								desc = L["Scale of the frame"],
								min = .1,
								max = 2,
								step = .1,
								order = 5,
							},
						},
					},
					font = {
						type = "group",
						name = L["Font"],
						desc = L["Font settings"],
						inline = true,
						order = 4,
						args = {
							globalFont = {
								type = "select",
								name = L["Global Font"],
								desc = L["Global font, used by the modules"],
								dialogControl = "LSM30_Font",
								values = AceGUIWidgetLSMlists.font,
								order = 1,
							},
							globalFontSize = {
								type = "range",
								name = L["Global Font Size"],
								desc = L["Text size of the power info text"],
								disabled = function()
									return not self.db.useGlobalFontSize
								end,
								min = 1, max = 20, step = 1,
								order = 5,
							},
							sep = {
								type = "description",
								name = "",
								width = "full",
								order = 7,
							},
							useGlobalFontSize = {
								type = "toggle",
								name = L["Use Global Font Size"],
								desc = L["Toggle if you want to use the global font size"],
								order = 10,
							},
						},
					},
				},
			},
		},
	}
	local order = 10
	for moduleName, module in pairsByKeys(self.modules) do
		self:SetupModule(moduleName, module, order)
		order = order + 5
	end
	for _, module in pairs(self.modules) do
		self:Call(module, "OptionsLoad")
	end
	self.options.plugins.profiles = {profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.dbi)}
	LibStub("AceConfig-3.0"):RegisterOptionsTable("Gladius", self.options)
	LibStub("AceConfigDialog-3.0"):AddToBlizOptions("Gladius", "Gladius")
end