local AddName, Ns = ...
local L = Ns.L
local HOptionsOffsetX, HOptionsOffsetY, mainMenuYOffset, separatorOffsetY = 7, 3, -82, 30
local sidePanelWidth
local redColor = { r=1, g=0, b=0.658 }
local orangeColor = { r=1, g=0.741, b=0.313 }
local white = { r=1, g=1, b=1 }

local addVer = C_AddOns.GetAddOnMetadata(AddName, "Version")
local groupTitles = {
	[2] = { text="GroupSetup", icon="Settings" },
	[3] = { text="GroupTextColor", icon="ValueColor" },
	[4] = { text="GroupStatusBars", icon="HUDBorder" },
}

-- compartment backgrounds
local groupIdentityStats = { Show = true, CustName = true }
local groupColorStats = { ColorCustom = true, ColorName = true, ColorClass = true, ColorValueEndable = true, ColorValue = true }
local function GetWidgetGroup(stat)
	if groupIdentityStats[stat] then return 1 end
	if Ns.BarKeys and Ns.BarKeys[stat] then return 4 end
	if groupColorStats[stat] then return 3 end
	return 2
end

if GetLocale() == 'zhCN' or GetLocale() == 'zhTW' or GetLocale() == 'koKR' then
    Ns.ConfigDefaultFont = Ns.LSM:Fetch("font", Ns.LSM:GetDefault("font"))
end
Ns.ConfigDefaultFontSize = 16
Ns.TooltipYOffset = 3
-----------------------------------------------
--			SV Items and Groupings			---
-----------------------------------------------
Ns.SettingsGroupOrder = {
	[1] = { stat="HUD", svnotintable=true, icon="HUD", widget={ type="TopTab" }, activeonload=true, },
	[2] = { stat="MinimapT", svnotintable=true, icon="MinimapIcon", widget={ type="TopTab" }, },
}

Ns.TextGroupOrder = {
	[1] = { stat="Text", svnotintable=true, icon="Fonts", widget={ type="TopTab" }, activeonload=true, },
}

Ns.LayoutGroupOrder = {
	[1] = { stat="DisplayOrder", description=true, svnotintable=true, icon="Layout", widget={ type="TopTab" }, enabledval=3, activeonload=true, },
}

Ns.LayoutDisplayOrder = { ignoretoptabs=true, 
	{ stat="StatOrderSettings", icon="", svnotintable=true, spellclass="DisplayOrder", widget={ type="DisplayOrderConfig", data="Profiles", width=200}, },
}

Ns.EventsGroupOrder = {
	[1] = { stat="Events", svnotintable=true, icon="Events", widget={ type="TopTab" }, activeonload=true, },
	[2] = { stat="EventSettings", svnotintable=true, icon="Settings", widget={ type="TopTab" }, },
}

Ns.EventsDisplayOrder = { --ignoretoptabs=true,
	--events
	{ stat="EventEnable", spellclass="Events", icon="", default=false, widget={ type="CheckBox", }, tooltip=true, linked={ "EventWorld", false, "EventDelves", false, "EventDungeon", false, "EventRaid", false, "EventPvP", false, "EventArena", false, "EventCombat", false, "EventResting", false, "EventMounted", false, "EventMouseOver", false }, onclick="ToggleMouseOver", },
	{ stat="EventWorld", spellclass="Events", icon="", default=false, widget={ type="CheckBox", }, newline=true, },
	{ stat="EventDelves", spellclass="Events", icon="", default=false, widget={ type="CheckBox", }, },
	{ stat="EventDungeon", spellclass="Events", icon="", default=false, widget={ type="CheckBox", }, },
	{ stat="EventRaid", spellclass="Events", icon="", default=false, widget={ type="CheckBox", }, },
	{ stat="EventPvP", spellclass="Events", icon="", default=false, widget={ type="CheckBox", }, newline=true, },
	{ stat="EventArena", spellclass="Events", icon="", default=false, widget={ type="CheckBox", }, },
	{ stat="EventCombat", spellclass="Events", icon="", default=false, widget={ type="CheckBox", }, },
	{ stat="EventMouseOver", spellclass="Events", icon="", default=false, widget={ type="CheckBox", }, onclick="ToggleMouseOver", },
	{ stat="EventResting", spellclass="Events", icon="", default=false, widget={ type="CheckBox", }, newline=true, },
	{ stat="EventMounted", spellclass="Events", icon="", default=false, widget={ type="CheckBox", }, },
	--setings
	{ stat="EventTimer", spellclass="EventSettings", icon="", default=false, widget={ type="CheckBox", }, linked={ "EventTime", false }, },
	{ stat="EventTime", spellclass="EventSettings", icon="", default=0.5, widget={ type="Slider", min=0.5, max=5, valuestep=0.5, width=170, }, },
	{ stat="EventOpacity", spellclass="EventSettings", icon="", default=false, widget={ type="CheckBox", }, tooltip=true, linked={ "EventOpacityValue", false }, newline=true, },
	{ stat="EventOpacityValue", spellclass="EventSettings", icon="", default=0.3, widget={ type="Slider", min=0, max=1, valuestep=0.05, width=170, }, },
}

Ns.ProfileGroupOrder = {
	[1] = { stat="Profiles", svnotintable=true, icon="Profiles", widget={ type="TopTab" }, activeonload=true, },
}

Ns.ProfileDisplayOrder = { ignoretoptabs=true, 
	{ stat="Profiles", icon="", svnotintable=true, spellclass="Profiles", widget={ type="ProfileConfig", data="Profiles", width=200, }, },
}

Ns.SearchGroupOrder = {
	[1] = { stat="Search", description=false, svnotintable=true, icon="Search", widget={ type="TopTab" }, enabledval=3, activeonload=true, },
}

Ns.SearchDisplayOrder = { ignoretoptabs=true,
	{ stat="Search", icon="", svnotintable=true, spellclass="Search", widget={ type="SearchConfig", data="Search", width=200, }, },
}

Ns.TextDisplayOrder = { ignoretoptabs=true,
	{ stat="StatFont", icon="", spellclass="Text", default="Arial Narrow",  widget={ type="DropList", data="Fonts", width=185, }, },
	{ stat="StatFontSize", icon="", spellclass="Text", default=16, widget={ type="Slider", min=8, max=45, valuestep=1, width=185, }, },
	{ stat="StatFontFlags", icon="", spellclass="Text", default="", widget={ type="DropList", data="FontFlags", width=150, }, },
	{ stat="FontShadow", icon="", spellclass="Text", default=false, widget={ type="CheckBox", }, linked={ "ShadowX", false, "ShadowY", false }, newline=true, },
	{ stat="ShadowX", icon="", spellclass="Text", default=1, widget={ type="Slider", min=-5, max=5, valuestep=1, width=185, }, },
	{ stat="ShadowY", icon="", spellclass="Text", default=-1, widget={ type="Slider", min=-5, max=5, valuestep=1, width=185, }, },	
	{ stat="StatWidth", icon="", spellclass="Text", default=150, widget={ type="Slider", min=70, max=500, valuestep=0.01, width=185, }, tooltip=true, subgroup={ text="FontsMenu", icon="Spacing" }, newline=true, },
	{ stat="StatSpacingH", icon="", spellclass="Text", default=1, widget={ type="Slider", min=1, max=100, width=185, }, },
	{ stat="StatSpacingV", icon="", spellclass="Text", default=0, widget={ type="Slider", min=0, max=100, valuestep=0.01, width=185, }, },
	{ stat="AlignValues", icon="", spellclass="Text", default=false, widget={ type="CheckBox", }, tooltip=true, linked={ "AlignGap", false }, newline=true, },
	{ stat="AlignGap", icon="", spellclass="Text", default=5, widget={ type="Slider", min=0, max=50, valuestep=1, width=185, }, },
	{ stat="StatAlignment", icon="", spellclass="Text", default="TOPLEFT", widget={ type="DropList", data="Alignments", width=110, }, newline=true, },
	{ stat="IconAlignment", icon="", spellclass="Text", default="TOPLEFT", widget={ type="DropList", data="IconAlignments", width=110, }, },
}

Ns.SettingsDisplayOrder = {
	{ stat="HideHUD", icon="", spellclass="HUD", default=false, widget={ type="CheckBox", }, },
	{ stat="LockHUD", icon="", spellclass="HUD", default=false, widget={ type="CheckBox", }, },
	{ stat="PanelDisplay", icon="", spellclass="HUD", default=false, widget={ type="CheckBox", }, },
	{ stat="HUDStrata", icon="", spellclass="HUD", default="MEDIUM", widget={ type="DropList", data="Strata", width=120, }, },
	{ stat="HUDBgTexture", icon="", spellclass="HUD", default="Solid", widget={ type="DropList", data="BarTextures", width=170, }, newline=true,},
	{ stat="HUDBgColor", icon="", spellclass="HUD", default={ r=0.1, g=0.1, b=0.1, }, widget={ type="ColorPicker", }, },
	{ stat="HUDBgAlpha", icon="", spellclass="HUD", default=0, widget={ type="Slider", min=0, max=1, valuestep=0.01, width=145, }, },
	{ stat="HUDBorder", icon="", spellclass="HUD", default=false, widget={ type="CheckBox", }, newline=true, },
	{ stat="HUDBorderColor", icon="", spellclass="HUD", default={ r=0.1, g=0.1, b=0.1, }, widget={ type="ColorPicker", }, },
	{ stat="HUDBorderSize", icon="", spellclass="HUD", default=1, widget={ type="Slider", min=1, max=6, valuestep=1, width=145, }, },
	{ stat="ResetPosition", icon="", spellclass="HUD", default=false, widget={ type="PlainButton", }, },
	{ stat="StatIcons", icon="", spellclass="HUD", default=true, widget={ type="CheckBox", }, subgroup={ text="Display", icon="Display", }, newline=true,},
	{ stat="StatTextCaps", spellclass="HUD", icon="", default=false, widget={ type="CheckBox", }, },
	{ stat="TextSeparator", icon="", spellclass="HUD", default=":", widget={ type="DropList", data="TextDataSeparator", width=90, },  },
	{ stat="HideText", icon="", spellclass="HUD", default=false, widget={ type="CheckBox", }, subgroup={ text="Display", icon="Display", }, },
	{ stat="StatTextColor", icon="", spellclass="HUD", default={ r=1, g=1, b=1, }, widget={ type="ColorPicker", }, newline=true, },
	{ stat="ClassColors", spellclass="HUD", icon="", default=false, widget={ type="CheckBox", }, },
	{ stat="SplitColors", spellclass="HUD", icon="", default=false, widget={ type="CheckBox", }, tooltip=true, },
	{ stat="DataColor", icon="", spellclass="HUD", default={ r=1, g=1, b=1, }, widget={ type="ColorPicker", }, },
	{ stat="Minimap", icon="", spellclass="MinimapT", default={ Show=true, }, widget={ type="MinimapButton", }, subgroup={ text="MinimapGroupText", icon="MinimapIcon", }, },
	{ stat="CompButton", spellclass="MinimapT", icon="", default=true, widget={ type="CheckBox", }, },
}

Ns.ProfileRootOrders = { Ns.SettingsDisplayOrder, Ns.TextDisplayOrder }

Ns.FAQGroupOrder = {
	[1] = { stat="FAQ", description=false, svnotintable=true, icon="Misc", widget={ type="TopTab" }, enabledval=3, activeonload=true, },
}

Ns.FAQDisplayOrder = { ignoretoptabs=true,
	{ stat="FAQ", icon="", svnotintable=true, spellclass="FAQ", widget={ type="FAQConfig", data="Profiles", width=200, }, },
}

--------------------------------------
--			Droplist tables			--
--------------------------------------
function Ns.CopyTable(src, dest)
	for index, value in pairs(src) do
		if type(value) == "table" then
			dest[index] = {}
			Ns.CopyTable(value, dest[index])
		else
			dest[index] = value
		end
	end
end

function Ns:CheckForStats(currentprofile, class)
	local statSettings = Ns:GetClassDefaults(class)
	for k, v in pairs(Ns.DefaultOrder) do
		if not currentprofile.Stats[v.stat] then
			currentprofile.Stats[v.stat] = {}
			currentprofile.Stats[v.stat].Show = statSettings[v.stat] or false
			if v.options then
				for o,_ in pairs(v.options) do
					for _, so in pairs(Ns.Options) do
						if so.stat == o and so.default ~= nil then
							currentprofile.Stats[v.stat][so.stat] = so.default
							break
						end
					end
				end
			end
		end
	end
end

function Ns:CreateProfile(newprofile, currentprofile, class) -- copies settings from the current to the new one
	if not currentprofile then
		if not class then
			print("Sinstats: No profile to copy from")
			return
		end
		currentprofile = {}
		for _, displayOrder in ipairs(Ns.ProfileRootOrders) do
			for _, options in pairs(displayOrder) do
				if type(options) == "table" and options.stat and not options.svnotintable then
					currentprofile[options.stat] = options.default
				end
			end
		end
		currentprofile.Stats = {}
		Ns:CheckForStats(currentprofile, class)
	end
	SinStatsDB.profiles[newprofile] = {}
	Ns.CopyTable(currentprofile, SinStatsDB.profiles[newprofile])
end

------------------------------------------
--			Design Functions			--
------------------------------------------
local function DisplayHorizontal(self, anchorframe, align, astab, noicons, ignoretoptabs)--, displayOrder, key, matchwith, noicons)
	local ChildAnchor
	anchorframe.HasScroll = nil
	anchorframe.TabScroll = nil
	if not astab then
		ChildAnchor = Ns:GetWidget("AnchorScroll" , anchorframe, 99999)
		anchorframe.HasScroll = ChildAnchor
		ChildAnchor.MyInformation = ChildAnchor.MyInformation or {}
		ChildAnchor:SetPoint("TOPLEFT", anchorframe.Description, 0, -30)
		ChildAnchor:SetPoint("BOTTOMRIGHT", Ns.ConfigFrame, -50, 10)
	else
		ChildAnchor = anchorframe
	end
	local largestWidgetWidth, largestWidgetHeight, sepOffset, tooltipOffset = 0, 0, 0
	--widget = widget and strtrim(widget) or nil  -- dead code: 'widget' is not a parameter or local (global leak)
	local tipped = {}
	for k, v in ipairs(self.DisplayOrder) do
		if not v.spellclass or v.spellclass == self.MyInformation.stat or (self.MyInformation.options and self.MyInformation.options[v.spellclass]) then
			local f = Ns:GetWidget(astab and "TopTab" or v.widget.type, ChildAnchor.ScrollChild and ChildAnchor.ScrollChild or anchorframe, k)
			anchorframe:AddWidget(f, ChildAnchor.ScrollChild and ChildAnchor.ScrollChild or anchorframe)
			f.ActiveOnInit = astab and v.activeonload -- must come before f:Init
			f:Init(anchorframe, self, noicons)
			local w = f:GetWidth()
			local h = f:GetHeight()
			if f.Tip then
				local tipW = f.Tip:GetWidth() + 20
				if tipW > largestWidgetWidth then
					largestWidgetWidth = tipW
				end
				tipped[f] = true
				if not tooltipOffset then
					tooltipOffset = f.Tip:GetHeight() + Ns.TooltipYOffset
				end
			end
			if w > largestWidgetWidth then
				largestWidgetWidth = w
			end
			if h > largestWidgetHeight then
				largestWidgetHeight = h
			end
			if v.tooltip then
				f.Tooltip = Ns:GetWidget("Tooltip", f)
				f.Tooltip:Init(f, v)
			end
		end
	end
	largestWidgetHeight = ceil(largestWidgetHeight)
	largestWidgetWidth = ceil(largestWidgetWidth)
 	local maxItemsPerRow = floor(Ns.maxOptionsWidth / (largestWidgetWidth + HOptionsOffsetX))
 	local rows, modOffset = 0, 1
 	local firstOnRow = ChildAnchor.ScrollChild and ChildAnchor.ScrollChild or anchorframe
 	local lastAnchor = firstOnRow
 	local cols = min(maxItemsPerRow, #anchorframe.CurrentWidgets)
 	local pageAlignment = anchorframe.CenterAlign and "TOP" or "TOPLEFT"
 	--local headerHeight = anchorframe.Description:GetHeight() + 24 -- y offset between header and top tabs
 	local headerHeight = 14 -- y offset between header and top tabs
 	local SubGroupLabel
	local SubGroupWidget
	local visibleRowCount = 0
	local addTip
	local groupInfo = {} -- tracks first/last row-start widget per group for compartment backgrounds
	local prevGroup
	if ignoretoptabs then
		largestWidgetHeight = 0
	else
		for k, v in ipairs(anchorframe.CurrentWidgets) do
			if astab then
				v:SetWidth(largestWidgetWidth)
			end
			v:ClearAllPoints()
			local modVal = (k-modOffset) % maxItemsPerRow
			if k == 1 or v.MyInformation.newline or modVal == 0 then
				addTip = 0
				for i=k, k + maxItemsPerRow do
					if anchorframe.CurrentWidgets[i] and anchorframe.CurrentWidgets[i].newline then
						break
					end
					if tipped[anchorframe.CurrentWidgets[i]] then
						addTip = tooltipOffset
						break
					end
				end
				local yos = addTip
				if k == 1 then
					yos = (HOptionsOffsetY * 2) + (headerHeight + 2) + anchorframe.Label:GetHeight()
				else
					if v.MyInformation.newline then
						modOffset = modOffset + modVal
					end
				end
				if v.Tip then
					yos = yos + 17  -- CHANGES THE Y OFFSET OF 1ST ROW AND 2ND ROW OPTIONS - TOGETHER
				end
			
				rows = rows + 1
				yos = k == 1 and -yos or -(yos + largestWidgetHeight + HOptionsOffsetY)
				if v.MyInformation.newline and v.MyInformation.subgroup then
					local multi = visibleRowCount == 1 and 32 or 25
					local push = (HOptionsOffsetY - 0.5) * multi
					local text = v.MyInformation.subgroup.text and v.MyInformation.subgroup.text or v.MyInformation.subgroup.stat
					SubGroupLabel = format(Ns.WidgetDisplayFormat, Ns:GetSpellIcon(v.MyInformation.subgroup), L[text])
					SubGroupWidget = v
					yos = yos - push - 25 -- adds extra spacing before subgroup if it's not the first row, and pushes the bottom separator down with the same amount
				end
				-- Add extra spacing between compartment groups
				if not astab and self.DisplayOrder == Ns.Options and k ~= 1 then
					local grp = GetWidgetGroup(v.MyInformation.stat)
					if prevGroup and grp ~= prevGroup then
						yos = yos - 38
					end
				end
				v:SetPoint("TOPLEFT", firstOnRow, "TOPLEFT", 0, yos)
				if k ~= 1 then
					local p, r, t, x, y = firstOnRow:GetPoint(1)
					if y then
						sepOffset = sepOffset + firstOnRow:GetHeight() + y + yos
					end
					visibleRowCount = visibleRowCount + 1
				end
				firstOnRow = v
				-- Track group boundaries for compartment backgrounds
				if not astab and self.DisplayOrder == Ns.Options then
					local grp = GetWidgetGroup(v.MyInformation.stat)
					prevGroup = grp
					if not groupInfo[grp] then
						groupInfo[grp] = { firstRowStart = v, lastRowStart = v }
					else
						groupInfo[grp].lastRowStart = v
					end
				end
				--savYos = yos
			else
				v:SetPoint(pageAlignment, lastAnchor, largestWidgetWidth + HOptionsOffsetX, 0)
			end
			lastAnchor = v
			if v.SetLink then
				v:SetLink(anchorframe, self)
			end
			v:Show() -- required because widgets are hidden when they are "killed"
		end
		-- Create compartment backgrounds for stat detail panels
		if not astab and self.DisplayOrder == Ns.Options and ChildAnchor and ChildAnchor.ScrollChild then
			local scrollChild = ChildAnchor.ScrollChild
			local pad = -3
			local contentWidth = Ns.maxOptionsWidth - 5
			for gNum, gData in pairs(groupInfo) do
				local bg = Ns:GetWidget("GroupBG", scrollChild)
				anchorframe:AddWidget(bg, scrollChild)
				bg.Texture:SetColorTexture(0.08020, 0.08020, 0.08020, 0.9)
				local grpInfo = groupTitles[gNum]
				local titleText = grpInfo and format(Ns.WidgetDisplayFormat, Ns:GetSpellIcon(grpInfo), L[grpInfo.text]) or ""
				local titlePad = titleText ~= "" and 15 or 0
				local identityPad = (gNum == 1) and 15 or 0 -- Extra top height for identity compartment (Show/Name)
				bg:SetPoint("TOPLEFT", gData.firstRowStart, "TOPLEFT", -3, 5 + titlePad + identityPad) -- Compartment BG top offset
				bg:SetPoint("BOTTOMLEFT", gData.lastRowStart, "TOPLEFT", -3, -(largestWidgetHeight + 3))
				bg:SetWidth(contentWidth + (pad * 2))
				bg:SetFrameLevel(max(scrollChild:GetFrameLevel(), 1))
				bg.Title:SetText(titleText)
				bg:Show()
			end
		end
	end
	if visibleRowCount == 2 then
		sepOffset = sepOffset + -(anchorframe.CurrentWidgets[1]:GetHeight() + (HOptionsOffsetY * 2))
	end
	local width
	if SubGroupLabel or not astab then
		anchorframe.TopSeparator = Ns:GetWidget("Separator", anchorframe)
		anchorframe.TopSeparator:SetPoint("CENTER", anchorframe, "TOP", 0, -28)
		anchorframe.TopSeparator:Show()
		if SubGroupLabel then
			anchorframe.BottomSeparator = Ns:GetWidget("Separator", anchorframe)

			if not astab then
				anchorframe.BottomSeparator:SetParent(ChildAnchor.ScrollChild)
			end
			anchorframe.BottomSeparator:Init()
			anchorframe.BottomSeparator:SetTextColor(1,1,1)
			anchorframe.BottomSeparator:SetLabel(SubGroupLabel)
			anchorframe.BottomSeparator:SetFont(Ns.ConfigDefaultFont2, Ns.ConfigDefaultFontSize - 2)
			local sepY = -(largestWidgetHeight + HOptionsOffsetY - 55) -- bottom separator offset, at 55 now
			if SubGroupWidget then
				anchorframe.BottomSeparator:SetPoint("TOP", SubGroupWidget, "TOPLEFT", Ns.SeparatorWidth / 2, sepY + largestWidgetHeight)
			elseif not astab then
				anchorframe.BottomSeparator:SetPoint("TOP", firstOnRow, "TOPLEFT", Ns.SeparatorWidth / 2, sepY)
			else
				anchorframe.BottomSeparator:SetPoint("CENTER", anchorframe, "TOP", 0, -(rows + 1) * (largestWidgetHeight + separatorOffsetY))
			end
			anchorframe.BottomSeparator:Show()
		else -- Adds bottom separator with description text
			anchorframe.BottomSeparator = Ns:GetWidget("Separator", anchorframe)
			anchorframe.BottomSeparator:Hide()
			if not astab then
				anchorframe.BottomSeparator:SetParent(ChildAnchor.ScrollChild)
			end
			anchorframe.BottomSeparator:Init(true)
			anchorframe.BottomSeparator:ClearAllPoints()
			local sepY = -(largestWidgetHeight + HOptionsOffsetY + 10)
			anchorframe.BottomSeparator:SetPoint("TOP", firstOnRow, "BOTTOMLEFT", Ns.SeparatorWidth / 2, sepY)
			if self.MyInformation.options or self.MyInformation.description then
				anchorframe.BottomSeparator:AnchorLabel("TOPLEFT", 5, -15, true)
				local text = string.trim(L[self.MyInformation.stat.."Description"])
				if text ~= "" then
					anchorframe.BottomSeparator:SetLabel(text)
					anchorframe.BottomSeparator:Show()
				end
			end
			anchorframe.BottomSeparator:SetTextColor(1,1,1) -- description text for stats
			anchorframe.BottomSeparator:SetFont(Ns.ConfigDefaultFont, Ns.ConfigDefaultFontSize - 4) -- font size
			anchorframe.BottomSeparator:EnableToolip(true)
			
		end

		width = Ns.SeparatorWidth
	else
		width = cols * (largestWidgetWidth + HOptionsOffsetX) - (rows == 1 and HOptionsOffsetX or 0)
	end
	local height
	if ignoretoptabs then
		height = 0
		for _, w in ipairs(anchorframe.CurrentWidgets) do
			local h = w:GetHeight()
			if h > height then height = h end
		end
		height = height + HOptionsOffsetY + 20
	else
		height = rows * (largestWidgetHeight + HOptionsOffsetY) + HOptionsOffsetY + headerHeight + anchorframe.Label:GetHeight() + 20
	end
	local maxTabRows = 4 -- add a scrollbar after these tab rows... reducing need to resize again
	if astab and rows > maxTabRows then
		local tabScroll = Ns:GetWidget("AnchorScroll", anchorframe, 99999)
		tabScroll.MyInformation = tabScroll.MyInformation or {}
		tabScroll.UpArrow:SetParent(anchorframe)
		tabScroll.DownArrow:SetParent(anchorframe)
		tabScroll.ScrollBar:SetParent(anchorframe)
		local headerTotalH = (HOptionsOffsetY * 2) + (headerHeight + 2) + anchorframe.Label:GetHeight()
		local rowH = largestWidgetHeight + HOptionsOffsetY
		local fullContentH = rows * rowH + HOptionsOffsetY + 4
		local visibleH = maxTabRows * rowH + HOptionsOffsetY + 4
		tabScroll:ClearAllPoints()
		tabScroll:SetPoint("TOPLEFT", anchorframe, "TOPLEFT", 0, -headerTotalH)
		tabScroll:SetSize(width, visibleH)
		tabScroll.ScrollChild:SetSize(width, fullContentH)
		for _, v in ipairs(anchorframe.CurrentWidgets) do
			v:SetParent(tabScroll.ScrollChild)
		end
		local firstWidget = anchorframe.CurrentWidgets[1]
		if firstWidget then
			local _, _, _, _, origY = firstWidget:GetPoint(1)
			firstWidget:ClearAllPoints()
			firstWidget:SetPoint("TOPLEFT", tabScroll.ScrollChild, "TOPLEFT", 0, -(HOptionsOffsetY + 2))
		end
		anchorframe:AddWidget(tabScroll)
		anchorframe.TabScroll = tabScroll
		height = visibleH + headerTotalH + 20
	end
	anchorframe:SetAnchor(align, width, height)-- + headerHeight)
	if not astab then
		anchorframe:AddWidget(ChildAnchor)
		ChildAnchor.ScrollChild:SetSize(width, height)
	end
end

function Ns:UpdateProfile()
	if not Ns.ConfigFrame then return end
	for i=0, #Ns.ConfigFrame.MainMenuItems do
		if i == 0 or i == 1 then
			Ns.ConfigFrame.MainMenuItems[i].SvTable = Ns.Profile
		else
			Ns.ConfigFrame.MainMenuItems[i].SvTable = Ns.Profile.Stats
		end
	end
end

----------------------------------
--			Main Menu			--
----------------------------------
local function CreateMainMenu()
	local last, click
	for i=0, #Ns.SpellClass do
		local v = Ns.SpellClass[i]
		local f = Ns:GetWidget("MainMenuButton", Ns.ConfigFrame, sidePanelWidth) -- -10)
		f:SetEnabled(true)
		if string.trim(Ns.SpellClass[i].stat) == "" then
			f:SetEnabled(false)
 		end
		Ns.ConfigFrame.MainMenuItems[i] = f
		f:SetID(i)
		--f:SetTextColor(orangeColor.r, orangeColor.g, orangeColor.b)
		f:SetTextColor(1,1,1)
		local iconPath = Ns:GetSpellIcon(v, Ns.IgnoreFormat)
		if iconPath and iconPath ~= "" then
			f.Icon:SetTexture(iconPath)
		else
			f.Icon:SetSize(0.1, 0.1)
		end
		f:SetLabel(L[Ns.SpellClass[i].stat])
		--f:SetFont(Ns.ConfigDefaultFont2)
		f:SetFontSize(13)
		f.SpellClass = v.stat
		if i == 0 then
			click = f
			f.DisplayOrder = Ns.SettingsGroupOrder
			f.GroupOrder = Ns.SettingsGroupOrder
			f.NextDisplayOrder = Ns.SettingsDisplayOrder
		elseif i == 1 then
			f.DisplayOrder = Ns.TextGroupOrder
			f.GroupOrder = Ns.TextGroupOrder
			f.NextDisplayOrder = Ns.TextDisplayOrder
		elseif i == 2 then
			f.DisplayOrder = Ns.LayoutGroupOrder
			f.GroupOrder = Ns.LayoutGroupOrder
			f.NextDisplayOrder = Ns.LayoutDisplayOrder
		elseif i == 3 then
			f.DisplayOrder = Ns.EventsGroupOrder
			f.GroupOrder = Ns.EventsGroupOrder
			f.NextDisplayOrder = Ns.EventsDisplayOrder
		elseif i == 4 then
			f.DisplayOrder = Ns.ProfileGroupOrder
			f.GroupOrder = Ns.ProfileGroupOrder
			f.NextDisplayOrder = Ns.ProfileDisplayOrder
		elseif i == 6 then
			f.DisplayOrder = Ns.SearchGroupOrder
			f.GroupOrder = Ns.SearchGroupOrder
			f.NextDisplayOrder = Ns.SearchDisplayOrder
		elseif v.stat == "FAQ" then
			f.DisplayOrder = Ns.FAQGroupOrder
			f.GroupOrder = Ns.FAQGroupOrder
			f.NextDisplayOrder = Ns.FAQDisplayOrder
		else  -- SpellClass Tabs
			f.DisplayOrder = Ns.DefaultOrder
			f.GroupOrder = Ns.SpellClass
			f.NextDisplayOrder = Ns.Options --Ns.OptionsList --Ns.GetStatOptionDefaults
--			f.SvTable = Ns.Profile.Stats
		end
		f.MyInformation = v
		f.DisplayFunc = DisplayHorizontal
		if i == 0 then
			f:SetPoint("TOPLEFT", Ns.ConfigFrame.TopBorder, "LEFT", 0, mainMenuYOffset) -- the first main menu item position relative to the top border line
			last = f
		else
			f:SetPoint("TOPLEFT", last, "BOTTOMLEFT", 0, -5)
			last = f
		end
 		Ns:UpdateProfile()
	end
	click:Click()
end

--------------------------------------
--			Config frame			--
--------------------------------------
local ColorBorders = Ns.ColorBorders
local CreateBorder = Ns.CreateBorder

local f = CreateFrame("frame", "SinStatsConfigFrame", UIParent)
f:SetPoint("CENTER")
f:SetMovable(true)
f:SetUserPlaced(true)
f:EnableMouse(true)
f:Hide()

local function InitConfig()
	local f = SinStatsConfigFrame
	Ns.ConfigFrame = f
	f.MainMenuItems = {} -- Toplevel items always visible

	f.Background = f:CreateTexture()
	f.Background:SetAllPoints()
	f.Background:SetColorTexture(0.09020, 0.09020, 0.09020, 1)
	f:SetSize(Ns.ConfigWidth or 800, Ns.ConfigHeight or 500)

	f.SideBackground = f:CreateTexture()
	f.SideBackground:SetDrawLayer("ARTWORK", 1)
	f.SideBackground:SetSize(151, Ns.ConfigHeight)
	f.SideBackground:SetPoint("TOPLEFT", 0, 0)
	f.SideBackground:SetColorTexture(0.08020, 0.08020, 0.08020, 0.5)

	f:SetClampedToScreen(false)
	f:RegisterForDrag("LeftButton")
	f:SetScript("OnDragStart", function(self) self:StartMoving() end)
	f:SetScript("OnDragStop", function(self) self:StopMovingOrSizing() end)
	f:SetFrameStrata("HIGH")
	tinsert(UISpecialFrames, Ns.ConfigFrame:GetName())
	f.Close = CreateFrame('Button', '$parentClose', f, "UIPanelCloseButton")
	f.Close:SetPoint('TOPRIGHT', -11, -5)
	f.Close:SetSize(15, 15)
	f.Close:SetFrameLevel(4)
	f.Close:SetHighlightTexture(Ns.TexturePath.."Close")
	f.Close:GetHighlightTexture():SetVertexColor(redColor.r, redColor.g, redColor.b, 1)
	f.Close:SetNormalTexture(Ns.TexturePath.."Close")
	f.Close:GetNormalTexture():SetVertexColor(white.r, white.g, white.b, 0.3)
	f.Close:SetPushedTexture(Ns.TexturePath.."Close")
	f.Close:GetPushedTexture():SetVertexColor(redColor.r, redColor.g, redColor.b, 0.9)
	f.Close:SetScript('OnClick', function(self)
		self:GetParent():Hide()
	end)

	f.Title = f:CreateFontString("$parentTitle", "OVERLAY")
	f.Title:SetFont(Ns.ConfigDefaultFont, Ns.ConfigDefaultFontSize)
	f.Title:SetPoint("TOP", 0, -15)
	f.Logo = f:CreateTexture("$parentLogo", "OVERLAY")
	f.Logo:SetTexture(Ns.TexturePath.."SinStatsLogo")
--[[
	f.Logo:SetSize(300, 300) -- So the frame isn't mostly blank when first opened (MainMenuScripts.OnClick for where it's moved)
	f.Logo:SetPoint("CENTER", 70, -10)
]]--
	f.Logo:SetSize(75, 75)
	f.Logo:SetPoint("TOPLEFT", 25, 3)

	f.Caption = CreateFrame("Frame", nil, f) -- Does the actual dragging
	f.Caption:SetPoint("TOPLEFT")
	f.Caption:SetPoint("BOTTOMRIGHT", f, "TOPRIGHT", 0, -50)

	f.TopBorder = f:CreateLine()
	f.TopBorder:SetDrawLayer("OVERLAY", 1)
	f.TopBorder:SetThickness(3)
	f.TopBorder:SetAlpha(0.5)
	f.TopBorder:SetStartPoint("BOTTOMLEFT", f.Caption, 10, 100)
	f.TopBorder:SetEndPoint("BOTTOMRIGHT", f.Caption, -10, -2)
	f.TopBorder:SetColorTexture(0.05, 0.05, 0.05, 0)

	-- local scale = f:GetEffectiveScale()
	-- local pixel = 1 / scale
	-- local sideX = math.floor(151 * scale + 0.5) / scale + pixel / 2
	-- f.SideBorder = f:CreateLine()
	-- f.SideBorder:SetDrawLayer("OVERLAY", 1)
	-- f.SideBorder:SetThickness(pixel)
	-- f.SideBorder:SetAlpha(1)
	-- f.SideBorder:SetStartPoint("LEFT", f.TopBorder, sideX - 10, 0)
	-- f.SideBorder:SetEndPoint("BOTTOMLEFT", f, sideX, 0)
	-- f.SideBorder:SetColorTexture(0, 0, 0)

	f.SideBorder = f:CreateLine()
	f.SideBorder:SetDrawLayer("OVERLAY", 1)
	f.SideBorder:SetThickness(1)
	f.SideBorder:SetAlpha(1)
	f.SideBorder:SetStartPoint("LEFT", f.TopBorder, 141, 0)
	f.SideBorder:SetEndPoint("BOTTOMLEFT", f, 151, 0)
	--f.SideBorder:SetColorTexture(unpack(borderColor))
	f.SideBorder:SetColorTexture(0, 0, 0)

	-- Corner textures
	f.topRight = f:CreateTexture("$parentTopRight", "OVERLAY")
	f.topRight:SetTexture(Ns.TexturePath.."top_right-corner")
	f.topRight:SetSize(20, 20)
	f.topRight:SetPoint("TOPRIGHT", 3, 3)

	f.bottomLeft = f:CreateTexture("$parentBotLeft", "OVERLAY")
	f.bottomLeft:SetTexture(Ns.TexturePath.."bottom_left-corner")
	f.bottomLeft:SetSize(20, 20)
	f.bottomLeft:SetPoint("BOTTOMLEFT", -3, -3)

	f.bottomRight = f:CreateTexture("$parentBotRight", "OVERLAY")
	f.bottomRight:SetTexture(Ns.TexturePath.."bottom_right-corner")
	f.bottomRight:SetSize(20, 20)
	f.bottomRight:SetPoint("BOTTOMRIGHT", 3, -3)

	f.topLeft = f:CreateTexture("$parentTopLeft", "OVERLAY")
	f.topLeft:SetTexture(Ns.TexturePath.."top_left-corner")
	f.topLeft:SetSize(20, 20)
	f.topLeft:SetPoint("TOPLEFT", -3, 3)

	-- Version
	f.Version = f:CreateFontString("$parentTitle", "OVERLAY")
	f.Version:SetFont(Ns.ConfigDefaultFont2, Ns.ConfigDefaultFontSize - 6)
	f.Version:SetPoint("BOTTOMLEFT", 65, 1)
	f.Version:SetText("|cff71ffc9" .. addVer .. "|r")

	local _, _, _, y = f.SideBorder:GetStartPoint()
	sidePanelWidth = select(3, f.SideBorder:GetStartPoint())
	Ns.maxOptionsWidth = f:GetWidth() - sidePanelWidth - 30 -- -30 right indent size
	Ns.SeparatorWidth  = Ns.maxOptionsWidth / 1.15
	f.TopAnchor = CreateFrame("Frame", nil, f)
	f.TopAnchor:SetSize(5, 2)
	f.TopAnchor:SetPoint("TOP", (sidePanelWidth/2), y-10) -- x,y entire right side panel content
	Ns.TopAnchor = f.TopAnchor

	CreateMainMenu()
	CreateBorder(f, 1)
	ColorBorders(f, 0, 0, 0)
end

function Ns:ToggleConfig()
	if not Ns.ConfigFrame then
		InitConfig()
	end
	Ns.ConfigFrame:SetShown(not Ns.ConfigFrame :IsShown())
end