--[[ Layouts Editor ]]--
local Grid2 = Grid2
local Grid2Options = Grid2Options

local L = Grid2Options.L
local LG = Grid2Options.LG

local Grid2Layout = Grid2:GetModule("Grid2Layout")

local DEFAULT_GROUP_ORDER = "WARRIOR,DEATHKNIGHT,ROGUE,PALADIN,DRUID,SHAMAN,PRIEST,MAGE,WARLOCK,HUNTER"
local DEFAULT_PET_ORDER = "HUNTER,WARLOCK,DEATHKNIGHT,PRIEST,MAGE,DRUID,SHAMAN,WARRIOR,ROGUE,PALADIN"

local TYPE_VALUES = {
	party = L["party"],
	raid = L["raid"],
	partypet = L["partypet"],
	raidpet = L["raidpet"]
}
local COLUMN_VALUES = {
	["1"] = "1",
	["2"] = "2",
	["3"] = "3",
	["4"] = "4",
	["5"] = "5",
	["6"] = "6",
	["7"] = "7",
	["8"] = "8"
}
local UPC_VALUES = {
	["all"] = L["all"],
	["01"] = "01",
	["02"] = "02",
	["03"] = "03",
	["04"] = "04",
	["05"] = "05",
	["10"] = "10",
	["15"] = "15",
	["20"] = "20",
	["25"] = "25"
}
local GROUP_VALUES = {
	["1"] = "1",
	["2"] = "2",
	["3"] = "3",
	["4"] = "4",
	["5"] = "5",
	["6"] = "6",
	["7"] = "7",
	["8"] = "8",
	["all"] = L["all"]
}
local GROUPBY_VALUES = {
	["CLASS"] = L["Class"],
	["GROUP"] = L["Group"],
	["ROLE"] = L["Role"],
	["NONE"] = L["None"]
}
local SORTBY_VALUES = {
	["NAME"] = L["Name"],
	["INDEX"] = L["Index"]
}

local ACTION1_VALUES = {
	add = string.format("|T%s:0|t%s", READY_CHECK_READY_TEXTURE, L["Insert"]),
	copy = string.format("|T%s:0|t%s", READY_CHECK_READY_TEXTURE, L["Copy"]),
	del = string.format("|T%s:0|t%s", READY_CHECK_NOT_READY_TEXTURE, L["Delete"])
}
local ACTION2_VALUES = {
	add = string.format("|T%s:0|t%s", READY_CHECK_READY_TEXTURE, L["Insert"]),
	copy = string.format("|T%s:0|t%s", READY_CHECK_READY_TEXTURE, L["Copy"])
}

local options
local layoutName
local LoadLayout

local function GetAvailableLayouts(info)
	local result = {}
	local layouts = Grid2Layout.layoutSettings
	local custom = Grid2Layout.db.global.customLayouts or {}
	for name in pairs(layouts) do
		result[name] = custom[name] and LG[name] .. " *" or LG[name]
	end
	return result
end

local function GetCustomLayout(name)
	if name then
		local layouts = Grid2Layout.db.global.customLayouts
		return layouts and layouts[name]
	end
end

local function GetHeaderOption(layout, header, option, default)
	return header[option] or (layout.defaults and layout.defaults[option]) or default
end

local function CreateNewGroupHeader(copyFrom)
	if copyFrom then
		local header = {}
		for k, v in pairs(copyFrom) do
			header[k] = v
		end
		return header
	else
		return {type = "raid", sortMethod = "INDEX", unitsPerColumn = 5, maxColumns = 1}
	end
end

local function LoadLayoutHeader(layoutName, layout, index, header)
	local order = index * 20
	local args = options.groups.args
	local disabled = not GetCustomLayout(layoutName)

	args["header" .. index] = {
		type = "header",
		order = order,
		name = string.format("%s %d", L["Header"], index)
	}
	args["type" .. index] = {
		type = "select",
		order = order + 5,
		width = "half",
		name = L["Type"],
		desc = L["Type of units to display"],
		get = function()
			return header.type or "raid"
		end,
		set = function(_, v)
			header.type = v
		end,
		values = TYPE_VALUES,
		disabled = disabled
	}
	args["columns" .. index] = {
		type = "select",
		order = order + 6,
		width = "half",
		name = L["Columns"],
		desc = L["Maximum number of columns to display"],
		get = function()
			return tostring(GetHeaderOption(layout, header, "maxColumns", 1))
		end,
		set = function(_, v)
			header.maxColumns = tonumber(v)
		end,
		values = COLUMN_VALUES,
		disabled = disabled
	}
	args["upc" .. index] = {
		type = "select",
		order = order + 7,
		width = "half",
		name = L["Units/Column"],
		desc = L["Maximum number of units per column to display"],
		get = function()
			local v = tostring(GetHeaderOption(layout, header, "unitsPerColumn", "all"))
			return strlen(v) > 1 and v or "0" .. v
		end,
		set = function(_, v)
			header.unitsPerColumn = tonumber(v)
		end,
		values = UPC_VALUES,
		disabled = disabled
	}
	args["group1" .. index] = {
		type = "select",
		order = order + 8,
		width = "half",
		name = L["First group"],
		desc = L["First group to display"],
		get = function()
			return header.groupFilter and strsub(header.groupFilter, 1, 1) or "all"
		end,
		set = function(_, v)
			v = tonumber(v)
			if v then
				local w = tonumber(header.groupFilter and strsub(header.groupFilter, -1)) or v
				local t = {}
				for i = v, math.max(v, w) do
					t[#t + 1] = tostring(i)
				end
				header.groupFilter = table.concat(t, ",")
			else
				header.groupFilter = nil
			end
		end,
		values = GROUP_VALUES,
		disabled = disabled
	}
	args["group2" .. index] = {
		type = "select",
		order = order + 9,
		width = "half",
		name = L["Last Group"],
		desc = L["Last group to display"],
		get = function()
			return header.groupFilter and strsub(header.groupFilter, -1) or "all"
		end,
		set = function(_, v)
			v = tonumber(v)
			if v then
				local w = tonumber(header.groupFilter and strsub(header.groupFilter, 1, 1)) or v
				local t = {}
				for i = w, math.max(v, w) do
					t[#t + 1] = tostring(i)
				end
				header.groupFilter = table.concat(t, ",")
			else
				header.groupFilter = nil
			end
		end,
		values = GROUP_VALUES,
		disabled = disabled
	}
	args["groupby" .. index] = {
		type = "select",
		order = order + 10,
		width = "half",
		name = L["Group by"],
		desc = L["Group by"],
		get = function()
			return GetHeaderOption(layout, header, "groupBy", "NONE")
		end,
		set = function(_, v)
			if v == "CLASS" then
				header.groupingOrder =
					(header.type == "raid" or header.type == "party") and DEFAULT_GROUP_ORDER or DEFAULT_PET_ORDER
			elseif v == "GROUP" then
				header.groupingOrder = header.groupFilter or "1,2,3,4,5,6,7,8"
			elseif v == "ROLE" then
				header.groupingOrder = "MAINTANK,MAINASSIST"
			else
				header.groupingOrder, v = nil, nil
			end
			header.groupBy = v
		end,
		values = GROUPBY_VALUES,
		disabled = disabled
	}
	args["sortby" .. index] = {
		type = "select",
		order = order + 10,
		width = "half",
		name = L["Sort by"],
		desc = L["Sort by"],
		get = function()
			return GetHeaderOption(layout, header, "sortMethod", "INDEX")
		end,
		set = function(_, v)
			header.sortMethod = v
		end,
		values = SORTBY_VALUES,
		disabled = disabled
	}
	if not disabled then
		args["action" .. index] = {
			type = "select",
			order = order + 12,
			width = "half",
			name = string.format("|cFF00ff00%s|r", L["Action"]),
			get = function()
			end,
			set = function(_, v)
				if v == "del" then
					if #layout > 1 then
						table.remove(layout, index)
						LoadLayout(layoutName)
					end
				else
					table.insert(layout, index + 1, CreateNewGroupHeader(v == "copy" and layout[index]))
					LoadLayout(layoutName)
				end
			end,
			values = #layout > 1 and ACTION1_VALUES or ACTION2_VALUES
		}
	end
end

local function LoadLayoutGeneralOptions(name)
	local args = options.groups.args
	local layout = Grid2Layout.layoutSettings[name]
	local isCustom = GetCustomLayout(name)
	args.separator1 = {
		type = "header",
		order = 1,
		name = L["General"]
	}
	args.scale = {
		type = "range",
		name = L["Scale"],
		desc = L["Adjust Grid scale."],
		order = 2,
		softMin = 0.5,
		softMax = 2.0,
		step = 0.05,
		isPercent = true,
		get = function()
			return Grid2Layout.db.profile.layoutScales[name] or 1
		end,
		set = function(_, v)
			Grid2Layout.db.profile.layoutScales[name] = (v ~= 1) and v or nil
			Grid2Layout:Scale()
		end
	}
	if isCustom then
		args.vehicle = {
			type = "toggle",
			name = L["Toggle for vehicle"],
			desc = L["When the player is in a vehicle replace the player frame with the vehicle frame."],
			order = 3,
			get = function()
				return layout.defaults.toggleForVehicle
			end,
			set = function()
				layout.defaults.toggleForVehicle = not layout.defaults.toggleForVehicle
			end
		}
	end
end

LoadLayout = function(name)
	wipe(options.groups.args)
	local layout = name and Grid2Layout.layoutSettings[name]
	if layout then
		LoadLayoutGeneralOptions(name)
		for i, h in ipairs(layout) do
			LoadLayoutHeader(name, layout, i, h)
		end
		return name
	end
end

local function CreateLayout(name)
	if Grid2Layout.layoutSettings[name] then
		return
	end
	local layouts = Grid2Layout.db.global.customLayouts
	if not layouts then
		layouts = {}
		Grid2Layout.db.global.customLayouts = layouts
	end
	layouts[name] = {
		meta = {raid40 = true, raid25 = true, raid20 = true, raid15 = true, raid10 = true, party = true, pvp = true, arena = true, solo = true},
		defaults = {toggleForVehicle = true, showPlayer = true, showParty = true, showRaid = true, showSolo = true},
		[1] = CreateNewGroupHeader()
	}
	Grid2Layout:AddLayout(name, layouts[name])
	options.selectLayout.values = GetAvailableLayouts()
	return LoadLayout(name)
end

function Grid2Options:RefreshCustomLayoutsOptions()
	layoutName = nil
	options.selectLayout.values = GetAvailableLayouts()
	LoadLayout(nil)
end

function Grid2Options:MakeLayoutsEditorOptions()
	layoutName = nil
	options = {
		selectLayout = {
			type = "select",
			order = 1,
			name = L["Select Layout"],
			desc = L["Select Layout"],
			values = GetAvailableLayouts,
			get = function()
				return layoutName
			end,
			set = function(_, v)
				layoutName = LoadLayout(v)
			end
		},
		newLayout = {
			type = "input",
			order = 2,
			name = L["New Layout Name"],
			desc = L["New Layout Name"],
			get = function()
			end,
			set = function(_, v)
				layoutName = CreateLayout(v)
			end
		},
		delete = {
			type = "execute",
			width = "half",
			order = 3,
			name = L["Delete"],
			desc = L["Delete selected layout"],
			func = function(info)
				Grid2Layout.db.global.customLayouts[layoutName] = nil
				Grid2Layout.layoutSettings[layoutName] = nil
				LoadLayout(nil)
				options.selectLayout.values = GetAvailableLayouts()
			end,
			hidden = function()
				return not GetCustomLayout(layoutName)
			end
		},
		refresh = {
			type = "execute",
			width = "half",
			order = 4,
			name = L["Refresh"],
			desc = L["Refresh the Layout"],
			func = function(info)
				if Grid2Layout.layoutName == layoutName then
					Grid2Layout:LoadLayout(layoutName)
				end
			end,
			hidden = function()
				return Grid2Layout.layoutName ~= layoutName or InCombatLockdown()
			end
		},
		groups = {
			type = "group",
			inline = true,
			name = "",
			order = 5,
			args = {}
		}
	}
	return options
end