local Recount = _G.Recount

local Graph = LibStub:GetLibrary("LibGraph-2.0")
local AceLocale = LibStub("AceLocale-3.0")
local L = AceLocale:GetLocale("Recount")

local revision = tonumber(string.sub("$Revision: 1563 $", 12, -3))
if Recount.Version < revision then
	Recount.Version = revision
end

local ipairs = ipairs
local math = math
local pairs = pairs
local string = string
local table = table
local tinsert = tinsert
local type = type

local CreateFrame = CreateFrame
local GetCursorPosition = GetCursorPosition
local GetMouseButtonClicked = GetMouseButtonClicked
local MouseIsOver = MouseIsOver

local UIParent = UIParent

local FauxScrollFrame_GetOffset = FauxScrollFrame_GetOffset
local FauxScrollFrame_OnVerticalScroll = FauxScrollFrame_OnVerticalScroll
local FauxScrollFrame_Update = FauxScrollFrame_Update

local me = {}

local Epsilon = 0.000000000000000001

local GraphColors = {
	Damage = {1.0, 0.0, 0.0, 1.0},
	DamageTaken = {1.0, 1.0, 0.0, 1.0},
	Healing = {0.0, 1.0, 0.0, 1.0},
	HealingTaken = {0.0, 1.0, 1.0, 1.0},
	Overhealing = {0.5, 0.0, 1.0, 1.0},
	Threat = {1.0, 0.5, 0, 1.0},
	TPS = {1.0, 0.6, 0.8, 1.0},
}

me.GraphColors = {}

local ClassCount = {}

local GraphName = {
	Damage = "Damage",
	DamageTaken = "Damage Taken",
	Healing = "Healing",
	HealingTaken = "Healing Taken",
	Overhealing = "Overhealing",
}

local ShadeVariant = {
	1.0, -- 1
	0.6, -- 2
	0.8, -- 3
	0.4, -- 4
	0.7, -- 5
	0.5, -- 6
	0.3, -- 7
	0.9, -- 8
}

function me:DataCopy(data)
	if not (data and data[1]) then
		return
	end

	local Copy = Recount:GetTable()
	Copy[1] = Recount:GetTable()
	Copy[2] = Recount:GetTable()
	for i = 1,#data[1] do
		Copy[1][i] = data[1][i]
		Copy[2][i] = data[2][i]
	end
	return Copy
end

function me:DataSparsen(data, amount)
	local Keep = Recount:GetTable()

	if #data[1] == 0 then
		return
	end

	local Min, Max, MinV, MaxV, CurVal
	local Time = data[1][1] + 0.5

	Keep[1] = true
	Min = 0

	for k, v in ipairs(data[1]) do
		CurVal = data[2][k]
		if v > Time and v < (Time + amount) then
			if Min == 0 then
				Min = k
				Max = k
				MinV = CurVal
				MaxV = CurVal
			elseif CurVal < MinV then
				Min = k
				MinV = CurVal
			elseif CurVal >= MaxV then
				Max = k
				MaxV = CurVal
			end
		elseif v >= (Time + amount) then
			if Min ~= 0 then
				Keep[Min] = true
				Keep[Max] = true
			end
			Time = v
			Min = k
			Max = k
			MinV = CurVal
			MaxV = CurVal
		end
	end
	if Min ~= 0 then
		Keep[Min] = true
		Keep[Max] = true

		Keep[#data[1]] = true
	end

	local i = #data[1]

	while i > 0 do
		if not Keep[i] then
			table.remove(data[1], i)
			table.remove(data[2], i)
		end
		i = i - 1
	end

	Recount:FreeTable(Keep)
end

function me:FilterDataByTime(data)
	local filtered = Recount:GetTable()
	filtered[1] = Recount:GetTable()
	filtered[2] = Recount:GetTable()

	local First = true
	local Last = 0

	for k, v in ipairs(data[1]) do
		if v >= Recount.TimeRangeLower and v <= Recount.TimeRangeUpper then
			--Need to add value right at the front edge
			if First then
				if k ~= 1 then
					--If not first need to LERP to find the edge value
					local Weight = (Recount.TimeRangeLower - data[1][k - 1]) / (data[1][k] - data[1][k - 1])
					filtered[2][#filtered[2] + 1] = Weight * data[2][k] + (1 - Weight) * data[2][k - 1]
				else
					--If this is first then insert 0 at front
					filtered[2][#filtered[2] + 1] = 0
				end
				filtered[1][#filtered[1] + 1] = Recount.TimeRangeLower
				First = false
			end
			filtered[1][#filtered[1] + 1] = v
			filtered[2][#filtered[2] + 1] = data[2][k]
			Last = k
		end
	end

	--Only add a trailer if we have data otherwise don't do anything
	if Last ~= 0 then
		--Do we have something we can LERP with?
		if data[1][Last + 1] then
			--Yes, so calculate a weight and then LERP
			local Weight = (Recount.TimeRangeUpper - data[1][Last]) / (data[1][Last + 1] - data[1][Last])
			filtered[2][#filtered[2] + 1] = Weight * data[2][Last + 1] + (1 - Weight) * data[2][Last]
		else
			--No so lets insert 0
			filtered[2][#filtered[2] + 1] = 0
		end
		filtered[1][#filtered[1] + 1] = Recount.TimeRangeUpper
	end

	return filtered
end

function me:FindMax(data)
	local Min = data[2][1]
	local Max = data[2][1]
	for _, v in ipairs(data[2]) do
		if v > Max then
			Max = v
		end
		if v < Min then
			Min = v
		end
	end
	return Min, Max
end

function me:SetMin(data, Min)
	for k, v in ipairs(data[2]) do
		if v < Min then
			data[2][k] = Min
		end
	end
end

function me:IntegrateData(data)
	local CurSum = 0
	local LastNum = 0
	local NotFirst = false
	for k, v in ipairs(data[1]) do
		if NotFirst then
			CurSum = CurSum + 0.5 * (data[2][k] + LastNum) * (v - data[1][k - 1])
			LastNum = data[2][k]
			data[2][k] = CurSum
		else
			LastNum = data[2][k]
			data[2][k] = 0
		end
		NotFirst = true
	end
end

function me:NormalizeData(data)
	local Min, Max = me:FindMax(data)
	local Width = Max - Min
	for k, v in ipairs(data[2]) do
		data[2][k] = 100 * (v - Min) / Width
	end
end
function me:HideTextures()
	if not self.Textures then
		self.Textures = {}
	end
	for k, t in pairs(self.Textures) do
		t:Hide()
	end
end

--Make sure to show a texture after you grab it or its free for anyone else to grab
function me:FindTexture()
	for k, t in pairs(self.Textures) do
		if not t:IsShown() then
			return t
		end
	end
	local g = self:CreateTexture(nil, "BACKGROUND")
	table.insert(self.Textures, g)
	return g
end

local function SortForStack(a, b)
	if a[1] > b[1] then
		return true
	elseif a[1] == b[1] and a[4] > b[4] then
		return true
	end
	return false
end

local function SortForDisplay(a, b)
	if a[1] < b[1] then
		return true
	elseif a[1] == b[1] and a[4] < b[4] then
		return true
	end
	return false
end

function me:AddDataSeries(a, b)
	--If ones nil just return the other one
	if a == nil or table.maxn(a) < 2 then
		return b
	elseif b == nil or table.maxn(b) < 2 then
		return a
	end

	local LastA, LastAT, Temp
	local PosA, PosB, LengthA, LengthB

	PosA = 1
	PosB = 1
	LengthA = table.maxn(a[1])
	LengthB = table.maxn(b[1])

	a[2][PosA] = math.max(a[2][PosA], 0)
	b[2][PosB] = math.max(b[2][PosB], 0)

	while PosA <= #a[1] or PosB <= LengthB do
		if PosA <= #a[1] then
			if PosB <= LengthB then
				if a[1][PosA] < b[1][PosB] then
					if PosB ~= 1 then
						--Need to lerp first calculate a weight
						Temp = (a[1][PosA] - b[1][PosB - 1]) / (b[1][PosB] - b[1][PosB - 1])
						--Now perform the lerp
						Temp = Temp * b[2][PosB] + (1 - Temp) * b[2][PosB - 1]
					else
						--If the first value can't lerp just pass the first value
						Temp = b[2][1]
					end
					LastAT = a[1][PosA]
					LastA = a[2][PosA]
					a[2][PosA] = a[2][PosA] + Temp
					PosA = PosA + 1
					if PosA <= LengthA and a[2][PosA] < 0 then
						a[2][PosA] = 0
					end
				elseif a[1][PosA] == b[1][PosB] then
					LastAT = a[1][PosA]
					LastA = a[2][PosA]
					a[2][PosA] = a[2][PosA] + b[2][PosB]
					PosA = PosA + 1
					PosB = PosB + 1
				else
					if PosA ~= 1 then
						--Need to lerp first calculate a weight
						Temp = (b[1][PosB] - LastAT) / (a[1][PosA] - LastAT)
						--Now perform the lerp
						Temp = Temp * a[2][PosA] + (1 - Temp) * LastA
					else
						--If the first value can't lerp just pass the first value
						Temp = a[2][1]
					end

					tinsert(a[1],PosA, b[1][PosB])
					tinsert(a[2],PosA, b[2][PosB] + Temp)
					PosA = PosA + 1
					PosB = PosB + 1

					if PosB <= LengthB and b[2][PosB] < 0 then
						b[2][PosB] = 0
					end
				end
			else
				LastAT = a[1][PosA]
				LastA = a[2][PosA]
				a[2][PosA] = a[2][PosA] + b[2][LengthB]
				PosA = PosA + 1
				if PosA <= LengthA and a[2][PosA] < 0 then
					a[2][PosA] = 0
				end
			end
		else
			--Then PosB must be <= LengthB
			a[1][PosA] = b[1][PosB]
			a[2][PosA] = b[2][PosB] + LastA
			PosB = PosB + 1
			PosA = PosA + 1
			if PosB <= LengthB and b[2][PosB] < 0 then
				b[2][PosB] = 0
			end
		end
	end
	return a
end

function me:DivideDataSeries(a, b)
	--If ones nil just return the other one
	if a == nil or table.maxn(a) < 2 then
		return b
	elseif b == nil or table.maxn(b) < 2 then
		return a
	end

	local LastA, LastB, Temp
	local PosA, PosB, LengthA, LengthB

	PosA = 1
	PosB = 1
	LengthA = #a[1]
	LengthB = #b[1]

	while PosA <= LengthA do
		if PosB <= LengthB then
			if a[1][PosA] <= b[1][PosB] then
				if PosB ~= 1 then
					--Need to lerp first calculate a weight
					Temp = (a[1][PosA] - b[1][PosB - 1]) / (b[1][PosB] - b[1][PosB - 1])
					--Now perform the lerp
					Temp = Temp * b[2][PosB] + (1 - Temp) * b[2][PosB - 1]
				else
					--If the first value can't lerp instead just pass the first value
					Temp = b[2][1]
				end

				if Temp ~= 0 then
					a[2][PosA] = (100 * a[2][PosA]) / Temp
				else
					a[2][PosA] = 0
				end

				if a[2][PosA] < 0 then
					a[2][PosA] = 0
				end

				PosA = PosA + 1
			else
				PosB = PosB + 1
				if PosB <= LengthB and b[2][PosB] < 0 then
					b[2][PosB] = 0
				end
			end
		else
			a[2][PosA] = 100*a[2][PosA] / (b[2][LengthB] + Epsilon)
			PosA = PosA + 1
		end
	end
end


function me:RefreshGraph()
	local Graph = Recount.GraphWindow.LineGraph
	local Length, MaxLength, Filtered, Result, MinAmount, MaxAmount, DataMax, Temp
	local Stacked = Recount:GetTable()

	Graph:ResetData()

	local i = 1
	MaxLength = 0
	MaxAmount = 0
	MinAmount = 0

	--If time range is not set need to find what will be used then
	if not Recount.TimeRangeSet then
		local TimeRangeLower, TimeRangeUpper
		if Recount.GraphWindow.Data then
			for k, v in pairs(Recount.GraphWindow.Data) do
				if v[1][1] then
					if TimeRangeLower == nil or v[1][1] < TimeRangeLower then
						TimeRangeLower = v[1][1]
					end
					if TimeRangeUpper == nil or v[1][table.maxn(v[1])] > TimeRangeUpper then
						TimeRangeUpper = v[1][table.maxn(v[1])]
					end
				end
			end
		end
		--Need to pretend like a Time Range is set then
		Recount.TimeRangeLower = TimeRangeLower
		Recount.TimeRangeUpper = TimeRangeUpper

		Graph:SetXAxis(TimeRangeLower, TimeRangeUpper)
		Graph:LockXMin(true)
		Graph:LockXMax(true)
	end

	if Recount.GraphWindow.Data then
		for k, v in pairs(Recount.GraphWindow.Data) do
			if type(v) == "table" and table.maxn(v[1]) > 0 and (v[1][1] ~= nil) and me.Enabled[k] then
				--Figure out the color used
				local color = me.GraphColors[k]

				--Start procecssing this data
				Filtered = me:FilterDataByTime(v)

				--Need to ensure its actually a copy if not then copy it
				if Filtered == v then
					Filtered = me:DataCopy(v)
				end

				if table.maxn(Filtered[1]) > 0 then
					if Recount.GraphWindow.IntegrateOn then
						me:IntegrateData(Filtered)
					end

					if not Recount.GraphWindow.StackedOn then
						Length = Filtered[1][table.maxn(Filtered[1])] - Filtered[1][1]

						if Length > 300 then
							me:DataSparsen(Filtered, Length / 100)
						end

						if Recount.GraphWindow.NormalizeOn then
							me:NormalizeData(Filtered)
						end

						local _
						_, DataMax = me:FindMax(Filtered)

						me:SetMin(Filtered, 0)

						if MaxAmount < DataMax then
							MaxAmount = DataMax
						end

						Graph:AddDataSeries(Filtered, color, true)

						if MaxLength < Length then
							MaxLength = Length
						end

						--Done with it so lets remove it
						Recount:FreeTableRecurse(Filtered)
					else
						--Stacked Graph Data needs to be stored for the moment
						local _
						_, DataMax = me:FindMax(Filtered)
						Temp = Recount:GetTable()
						Temp[1] = DataMax
						Temp[2] = Filtered
						Temp[3] = color
						Temp[4] = k
						table.insert(Stacked, Temp)
					end
				end
			end
			i = i + 1
		end
	end

	if Recount.GraphWindow.StackedOn then
		local Current = Recount:GetTable()
		table.sort(Stacked, SortForStack)

		for k, v in pairs(Stacked) do
			for k2, v2 in pairs(v[2][2]) do
				if v2 < 0 then
					v[2][2][k2] = 0
				end
			end
		end

		for k, v in pairs(Stacked) do
			Length = v[2][1][table.maxn(v[2][1])] - v[2][1][1]

			if Length > 200 then
				me:DataSparsen(v[2], Length / 70)
			end

			Current = me:AddDataSeries(v[2],Current)
			if Current ~= v[2] then
				Recount:FreeTableRecurse(v[2])
				v[2] = Current
			end
		end
		if Recount.GraphWindow.NormalizeOn then
			--Divide now by the total
			local Total = me:DataCopy(Current)
			for k, v in pairs(Stacked) do
				me:DivideDataSeries(v[2], Total)
			end
		end

		table.sort(Stacked, SortForDisplay)
		if Stacked[1] and Stacked[1][2] then
			local _
			_, MaxAmount = me:FindMax(Stacked[1][2])

			for k, v in pairs(Stacked) do
				Length = v[2][1][table.maxn(v[2][1])] - v[2][1][1]

				if Length > 200 then
					me:DataSparsen(v[2], Length / 70)
				end

				if MaxLength < Length then
					MaxLength = Length
				end

				Graph:AddFilledDataSeries(v[2], v[3], true)
				--Recount:PrintLiteral(v[2])
				--break
			end
		end
		--Can't free current because its already in there
		Recount:FreeTableRecurse(Current)
		for k, v in pairs(Stacked) do
			Recount:FreeTableRecurse(v[2])
			Recount:FreeTable(v)
		end
		Recount:FreeTable(Stacked)
	end

	Graph:SetYAxis(0, MaxAmount)

	if MaxAmount < 100 then
		DataMax = 10
	elseif MaxAmount < 250 then
		DataMax = 25
	elseif MaxAmount < 500 then
		DataMax = 50
	elseif MaxAmount < 1500 then
		DataMax = 100
	elseif MaxAmount < 3000 then
		DataMax = 200
	else
		DataMax = 100 * math.floor(MaxAmount / 1000)
	end

	local XMin = Graph.XMin
	local XMax = Graph.XMax

	--Hack fix for no data
	if XMin == nil or XMax == nil then
		Graph:SetXAxis(5, 30)
		XMin = Graph.XMin
		XMax = Graph.XMax
	end

	MaxLength = XMax - XMin

	if MaxLength < 60 then
		Graph:SetGridSpacing(5, DataMax)
		Graph.TimeRef:SetText(L["X Gridlines Represent"].." 5 "..L["Seconds"])
	elseif MaxLength < 180 then
		Graph:SetGridSpacing(15, DataMax)
		Graph.TimeRef:SetText(L["X Gridlines Represent"].." 15 "..L["Seconds"])
	elseif MaxLength < 400 then
		Graph:SetGridSpacing(30, DataMax)
		Graph.TimeRef:SetText(L["X Gridlines Represent"].." 30 "..L["Seconds"])
	elseif MaxLength < 600 then
		Graph:SetGridSpacing(60, DataMax)
		Graph.TimeRef:SetText(L["X Gridlines Represent"].." 60 "..L["Seconds"])
	else
		Graph:SetGridSpacing(math.floor(MaxLength / 100) * 10, DataMax)
		Graph.TimeRef:SetText(L["X Gridlines Represent"].." "..(math.floor(MaxLength / 100) * 10).." "..L["Seconds"])
	end

	local Background = Recount.GraphWindow.GraphBackground
	Background:HideTextures()

	local CurPos = XMin
	local Width = Background:GetWidth() / (XMax - XMin)
	local T
	--Code for drawing the various fights with a red background
	for k, v in ipairs(Recount.db2.CombatTimes) do
		if CurPos < v[1] then
			if v[1] > XMax then
				return
			end

			T = Background:FindTexture()
			T:Show()
			if Recount.GraphWindow.LastTimeOver ~= k then
				T:SetColorTexture(1, 0, 0, 0.1)
			else
				T:SetColorTexture(1, 1, 0, 0.1)
			end
			T:SetPoint("TOPLEFT", Background, "TOPLEFT", (v[1] - XMin) * Width, 0)
			if v[2] > XMax then
				T:SetPoint("BOTTOMRIGHT", Background, "BOTTOMRIGHT", 0, 0)
				return
			end
			T:SetPoint("BOTTOMRIGHT", Background, "BOTTOMLEFT", (v[2] - XMin) * Width, 0)
			T.id = k
			CurPos = v[2]
		elseif CurPos < v[2] then
			T = Background:FindTexture()
			T:Show()
			if Recount.GraphWindow.LastTimeOver ~= k then
				T:SetColorTexture(1, 0, 0, 0.1)
			else
				T:SetColorTexture(1, 1, 0, 0.1)
			end
			T:SetPoint("TOPLEFT", Background, "TOPLEFT", (CurPos - XMin) * Width, 0)
			if v[2] > XMax then
				T:SetPoint("BOTTOMRIGHT", Background, "BOTTOMRIGHT", 0, 0)
				return
			end
			T:SetPoint("BOTTOMRIGHT", Background, "BOTTOMLEFT", (v[2] - XMin) * Width, 0)
			T.id = k
			CurPos = v[2]
		end
	end
end

function me:SelectCombatTimes(id)
	local Graph = Recount.GraphWindow.LineGraph
	local Rows = Recount.GraphWindow.TimeRows

	local offset = FauxScrollFrame_GetOffset(Recount.GraphWindow.ScrollBar2)

	if Recount.TimeRangeSet == (id + offset) then
		Recount.TimeRangeSet = false
		Rows[id].Background:Hide()
		Graph:LockXMin(false)
		Graph:LockXMax(false)
		me:RefreshGraph()
		return
	end

	Recount.TimeRangeSet = id + offset
	local Times = Recount.db2.CombatTimes[id + offset]

	Recount.TimeRangeLower = Times[1] - 30
	Recount.TimeRangeUpper = Times[2] + 30

	for i = 1, 10 do
		Rows[i].Background:Hide()
	end

	Rows[id].Background:Show()

	Graph:LockXMin(true)
	Graph:LockXMax(true)
	Graph:SetXAxis(Recount.TimeRangeLower, Recount.TimeRangeUpper)
	me:RefreshGraph()
end

function me:SelectCombatTime(time)
	for k, v in pairs(Recount.db2.CombatTimes) do
		if v[1] <= time and time <= v[2] then
			local Graph = Recount.GraphWindow.LineGraph
			Recount.TimeRangeSet = k
			Recount.TimeRangeLower = v[1] - 30
			Recount.TimeRangeUpper = v[2] + 30
			Graph:LockXMin(true)
			Graph:LockXMax(true)
			Graph:SetXAxis(Recount.TimeRangeLower, Recount.TimeRangeUpper)
			me:RefreshGraph()
			Recount:GraphRefreshCombat()
			return
		end
	end
end

function me:HighlightCombatTime(time)
	local TimeOver = nil
	if time then
		for k, v in pairs(Recount.db2.CombatTimes) do
			if v[1] <= time and time <= v[2] then
				TimeOver = k
				break
			end
		end
	end

	if TimeOver ~= Recount.GraphWindow.LastTimeOver then
		for _, v in pairs(Recount.GraphWindow.GraphBackground.Textures) do
			if v.id == TimeOver then
				v:SetColorTexture(1, 1, 0, 0.1)
			elseif v.id == Recount.GraphWindow.LastTimeOver then
				v:SetColorTexture(1, 0, 0, 0.1)
			end
		end

		Recount.GraphWindow.LastTimeOver = TimeOver
	end
end

function Recount:CheckFontStringLength(fontstring, maxwidth)
	local Text = fontstring:GetText()

	while fontstring:GetStringWidth() > maxwidth do
		Text = string.sub(Text, 1, string.len(Text) - 1)
		fontstring:SetText(Text.."...")
	end
end

function Recount:SetGraphData(name, data, combat)
	Recount.GraphWindow.Title:SetText(L["Graph Window"].." - "..name)
	Recount.GraphWindow.Data = data
	Recount.GraphWindow.CombatTime = combat
	Recount.GraphWindow:Show()
	Recount:SetWindowTop(Recount.GraphWindow)

	--Need to reset class counts if in compare mode
	if Recount.GraphCompare then
		for k, _ in pairs(ClassCount) do
			ClassCount[k] = nil
		end
	end
	local Class, Shade

	if me.Enabled == nil then
		me.Enabled = {}
	end

	local i = 1
	if Recount.GraphWindow.Data then
		for k, _ in pairs(Recount.GraphWindow.Data) do
			local color = GraphColors[k]

			if type(color) ~= "table" then
				if Recount.GraphCompare and Recount.GraphClass[k] then
					Class = Recount.GraphClass[k]
					ClassCount[Class] = (ClassCount[Class] or 0) + 1
					if ClassCount[Class] <= 8 then
						Shade = ShadeVariant[ClassCount[Class]]
						color = {Shade * Recount.db.profile.Colors.Class[Class].r, Shade * Recount.db.profile.Colors.Class[Class].g, Shade * Recount.db.profile.Colors.Class[Class].b, 1}
					else
						color = {math.random(), math.random(), math.random(), 1}
					end
				else
					color = {math.random(), math.random(), math.random(), 1}
				end
			end

			me.GraphColors[k] = color
			me.Enabled[k] = true

			if i <= 10 then
				Recount.GraphWindow.Rows[i]:Show()
				Recount.GraphWindow.Rows[i].Key:SetVertexColor(color[1], color[2], color[3], 1)
				Recount.GraphWindow.Rows[i].Name:SetText(GraphName[k] or k)
			end

			i = i + 1
		end
	end

	Recount.GraphWindow.Entries = i - 1

	for j = i, 10 do
		Recount.GraphWindow.Rows[j]:Hide()
	end

	Recount:GraphRefreshData()
	Recount:GraphRefreshCombat()

	me:RefreshGraph()
end

function Recount:GraphRefreshData()
	local data = Recount.GraphWindow.Data
	local size = Recount.GraphWindow.Entries
	FauxScrollFrame_Update(Recount.GraphWindow.ScrollBar1, size, 10, 20)
	local offset = FauxScrollFrame_GetOffset(Recount.GraphWindow.ScrollBar1)
	local Rows = Recount.GraphWindow.Rows
	local i = 1 - offset

	if Recount.GraphWindow.Data then
		for k, v in pairs(Recount.GraphWindow.Data) do
			if i >= 1 and i <= 10 then
				Rows[i]:Show()
				Rows[i].Key:SetVertexColor(me.GraphColors[k][1], me.GraphColors[k][2], me.GraphColors[k][3], 1)
				Rows[i].Name:SetText(GraphName[k] or k)
				Recount:CheckFontStringLength(Rows[i].Name, 180)
				Rows[i].Enabled:SetChecked(me.Enabled[k])
				Rows[i].Enabled.Key = k
			end
			i = i + 1
		end
	end

	while i <= 10 do
		Rows[i]:Hide()
		i = i + 1
	end
end

function Recount:GraphRefreshCombat()
	local combat = Recount.db2.CombatTimes
	local size = table.getn(combat)
	FauxScrollFrame_Update(Recount.GraphWindow.ScrollBar2, size, 10, 20)
	local offset = FauxScrollFrame_GetOffset(Recount.GraphWindow.ScrollBar2)
	local Rows = Recount.GraphWindow.TimeRows

	for i = 1, 10 do
		local c = combat[i + offset]
		if c then
			Rows[i]:Show()
			Rows[i].Who:SetText(c[5])
			Recount:CheckFontStringLength(Rows[i].Who, 115)
			Rows[i].Start:SetText(c[3])
			Rows[i].End:SetText(c[4])

			if i + offset ~= Recount.TimeRangeSet then
				Rows[i].Background:Hide()
			else
				Rows[i].Background:Show()
			end
		else
			Rows[i]:Hide()
		end
	end
end

function Recount:CreateGraphWindow()
	Recount.GraphWindow = CreateFrame("Frame", "Recount_GraphWindow", UIParent, BackdropTemplateMixin and "BackdropTemplate")

	local theFrame = Recount.GraphWindow

	theFrame.Me = me

	theFrame:ClearAllPoints()
	theFrame:SetPoint("CENTER", UIParent)
	theFrame:SetHeight(432 + 20)
	theFrame:SetWidth(625 + 24)

	theFrame:SetBackdrop({
		bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16,
		edgeFile = "Interface\\AddOns\\Recount\\textures\\otravi-semi-full-border", edgeSize = 32,
		insets = {left = 1, right = 1, top = 20, bottom = 1},
	})
	theFrame:SetBackdropBorderColor(1.0, 0.0, 0.0)
	theFrame:SetBackdropColor(24 / 255, 24 / 255, 24 / 255)
	Recount.Colors:RegisterBorder("Other Windows", "Title", theFrame)
	Recount.Colors:RegisterBackground("Other Windows", "Background", theFrame)

	theFrame:EnableMouse(true)
	theFrame:SetMovable(true)
	--theFrame:RegisterForDrag("LeftButton")
	--theFrame:SetScript("OnDragStart",theFrame.StartMoving)
	--theFrame:SetScript("OnDragStop",theFrame.StopMovingOrSizing)

	theFrame:SetFrameLevel(Recount.MainWindow:GetFrameLevel() + 20)

	theFrame:SetScript("OnMouseDown", function(this, button)
		if (((not this.isLocked) or (this.isLocked == 0)) and (button == "LeftButton")) then
			Recount:SetWindowTop(this)
			this:StartMoving()
			this.isMoving = true
		end
	end)
	theFrame:SetScript("OnMouseUp", function(this)
		if (this.isMoving) then
			local point, relativeTo, relativePoint, xOfs, yOfs = this:GetPoint(1)
			Recount.db.profile.GraphWindowX = xOfs
			Recount.db.profile.GraphWindowY = yOfs
			this:StopMovingOrSizing()
			this.isMoving = false
		end
	end)
	theFrame:SetScript("OnShow", function(this)
		Recount:SetWindowTop(this)
	end)
	theFrame:SetScript("OnHide", function(this)
		if (this.isMoving) then
			local point, relativeTo, relativePoint, xOfs, yOfs = this:GetPoint(1)
			Recount.db.profile.GraphWindowX = xOfs
			Recount.db.profile.GraphWindowY = yOfs
			this:StopMovingOrSizing()
			this.isMoving = false
		end
	end)

	theFrame.Title = theFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	theFrame.Title:SetPoint("TOPLEFT", theFrame, "TOPLEFT", 6, -15)
	theFrame.Title:SetTextColor(1.0, 1.0, 1.0, 1.0)
	theFrame.Title:SetText(L["Graph Window"])

	--Recount.Colors:UnregisterItem(Recount.GraphWindow.Title)
	Recount.Colors:RegisterFont("Other Windows", "Title Text", Recount.GraphWindow.Title)

	theFrame.LineGraph = Graph:CreateGraphLine("Recount_GraphWindow_LineGraph", theFrame, "TOPLEFT", "TOPLEFT", 1, -32, 400, 418)
	theFrame.LineGraph:SetAutoScale(true)
	theFrame.LineGraph:SetYAxis(0, 100)
	theFrame.LineGraph:SetGridSpacing(15, 25)
	theFrame.LineGraph:LockYMin(true)
	theFrame.LineGraph:SetYLabels(true, true)
	theFrame.LineGraph:SetFrameLevel(theFrame:GetFrameLevel() + 2)
	theFrame.LineGraph.TimeRef = theFrame.LineGraph:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	theFrame.LineGraph.TimeRef:SetPoint("TOP", theFrame.LineGraph, "TOP", 0, -2)
	theFrame.LineGraph.TimeRef:SetTextColor(1.0, 1.0, 1.0, 1.0)

	theFrame.GraphBackground = CreateFrame("Frame", nil, theFrame)
	theFrame.GraphBackground:SetAllPoints(theFrame.LineGraph)
	theFrame.GraphBackground.HideTextures = me.HideTextures
	theFrame.GraphBackground.FindTexture = me.FindTexture

	theFrame.GraphBackground:EnableMouse(true)

	theFrame.GraphBackground.TimeSelect = theFrame.GraphBackground:CreateTexture(nil, "BACKGROUND")
	theFrame.GraphBackground.TimeSelect:SetColorTexture(0, 1, 0, 0.1)
	theFrame.GraphBackground.TimeSelect:Hide()


	theFrame.GraphBackground:SetScript("OnUpdate", function(this)
		local sX = this:GetCenter()
		local Scale = this:GetEffectiveScale()
		local mX = GetCursorPosition()
		local TimePos
		local GraphWindow = Recount.GraphWindow

		if Recount.TimeRangeUpper and (MouseIsOver(GraphWindow.GraphBackground) or Recount.GraphWindow.Dragging) then
			TimePos = (mX / Scale - sX + this:GetWidth() / 2) / this:GetWidth()
			TimePos = TimePos * (Recount.TimeRangeUpper - Recount.TimeRangeLower) + Recount.TimeRangeLower

			if MouseIsOver(GraphWindow.GraphBackground) then
				me:HighlightCombatTime(TimePos)
			end

			if GraphWindow.Dragging then
				local Graph = GraphWindow.LineGraph
				local Background = GraphWindow.GraphBackground

				local XMin = Graph.XMin
				local XMax = Graph.XMax

				--Hack fix for no data
				if XMin == nil or XMax == nil then
					Graph:SetXAxis(5, 30)
					XMin = Graph.XMin
					XMax = Graph.XMax
				end

				local Width = Background:GetWidth() / (XMax - XMin)

				local Left, Right

				Left = math.max(math.min(GraphWindow.DragTimeStart, XMax),XMin)
				Right = math.max(math.min(TimePos, XMax),XMin)

				if Right < Left then
					local t = Left
					Left = Right
					Right = t
				end

				Background.TimeSelect:SetPoint("TOPLEFT", Background, "TOPLEFT", (Left - XMin) * Width, 0)
				Background.TimeSelect:SetPoint("BOTTOMRIGHT", Background, "BOTTOMLEFT", (Right - XMin) * Width, 0)
			end
		end
	end)
	theFrame.GraphBackground:SetScript("OnMouseDown", function(this)
		local sX = this:GetCenter()
		local Scale = this:GetEffectiveScale()
		local mX = GetCursorPosition()
		local TimePos

		if Recount.TimeRangeUpper then
			TimePos = (mX / Scale - sX + this:GetWidth() / 2) / this:GetWidth()
			TimePos = TimePos * (Recount.TimeRangeUpper - Recount.TimeRangeLower) + Recount.TimeRangeLower

			--If we start dragging we want this to be the start position
			Recount.GraphWindow.DragTimeStart = TimePos
		end
	end)
	theFrame.GraphBackground:SetScript("OnMouseUp", function(this)
		if Recount.GraphWindow.Dragging then
			Recount.GraphWindow.Dragging = false
			return
		end
		if GetMouseButtonClicked() == "RightButton" then
			Recount.TimeRangeSet = false
			me:RefreshGraph()
			Recount:GraphRefreshCombat()
		elseif GetMouseButtonClicked() == "LeftButton" then
			local sX = this:GetCenter()
			local Scale = this:GetEffectiveScale()
			local mX = GetCursorPosition()
			local TimePos

			if Recount.TimeRangeUpper then -- Elsia: Prevent nil error
				TimePos = (mX / Scale - sX + this:GetWidth() / 2) / this:GetWidth()
				TimePos = TimePos * (Recount.TimeRangeUpper - Recount.TimeRangeLower) + Recount.TimeRangeLower
				me:SelectCombatTime(TimePos)
			end
		end
	end)
	theFrame.GraphBackground:SetScript("OnDragStart", function()
		Recount.GraphWindow.Dragging = true
		--Recount.GraphWindow.DragTimeStart = TimePos
		Recount.GraphWindow.GraphBackground.TimeSelect:Show()
	end)
	theFrame.GraphBackground:SetScript("OnDragStop", function(this)
		--First get cur time pos
		local sX = this:GetCenter()
		local Scale = this:GetEffectiveScale()
		local mX = GetCursorPosition()
		local TimePos

		if Recount.TimeRangeUpper then -- Elsia: Prevent nil error
			TimePos = (mX / Scale - sX + this:GetWidth() / 2) / this:GetWidth()
			TimePos = TimePos * (Recount.TimeRangeUpper - Recount.TimeRangeLower) + Recount.TimeRangeLower
			me:HighlightCombatTime(TimePos)
		end

		--Need XMin and XMax of the graph
		local Graph = Recount.GraphWindow.LineGraph
		local XMin = Graph.XMin
		local XMax = Graph.XMax

		--Hack fix for no data
		if XMin == nil or XMax == nil then
			Graph:SetXAxis(5, 30)
			XMin = Graph.XMin
			XMax = Graph.XMax
		end

		--Now figure out left and right
		local Left, Right

		if Recount.GraphWindow.DragTimeStart then
			Left = math.max(math.min(Recount.GraphWindow.DragTimeStart, XMax), XMin)
			Right = math.max(math.min(TimePos, XMax), XMin)

			if Right < Left then
				local t = Left
				Left = Right
				Right = t
			end
		end

		--Now to set the graph
		Recount.TimeRangeSet = true
		Recount.TimeRangeLower = Left
		Recount.TimeRangeUpper = Right
		Graph:LockXMin(true)
		Graph:LockXMax(true)
		Graph:SetXAxis(Recount.TimeRangeLower, Recount.TimeRangeUpper)
		me:RefreshGraph()

		Recount.GraphWindow.GraphBackground.TimeSelect:Hide()
	end)
	theFrame.GraphBackground:RegisterForDrag("LeftButton")



	theFrame.Labels = CreateFrame("Frame", nil, theFrame)
	local Labels = theFrame.Labels

	Labels:SetWidth(219)
	Labels:SetHeight(16)
	Labels:SetPoint("TOPRIGHT", theFrame, "TOPRIGHT", -1 - 24, -34)

	Labels.Key = Labels:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	Labels.Key:SetPoint("LEFT", Labels, "LEFT", 1, 0)
	Labels.Key:SetText("K")

	Labels.Name = Labels:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	Labels.Name:SetPoint("LEFT", Labels, "LEFT", 16, 0)
	Labels.Name:SetText(L["Data Name"])

	Labels.Name = Labels:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	Labels.Name:SetPoint("Right", Labels, "RIGHT", -2, 0)
	Labels.Name:SetText(L["Enabled"])

	theFrame.Rows = {}

	for i = 1, 10 do
		local Row = CreateFrame("Frame", nil, theFrame)
		Row:SetWidth(219)
		Row:SetHeight(16)
		Row:SetPoint("TOPRIGHT", theFrame, "TOPRIGHT", -1 - 24, -34 - i * 18)

		Row.Key = Row:CreateTexture("RecountRowTexture"..i,"OVERLAY")
		Row.Key:SetPoint("LEFT", Row, "LEFT", 0, 0)
		Row.Key:SetTexture("Interface\\Buttons\\WHITE8X8.blp")
		Row.Key:SetWidth(12)
		Row.Key:SetHeight(12)

		Row.Name = Row:CreateFontString(nil, "OVERLAY", "GameFontNormal")
		Row.Name:SetPoint("LEFT", Row, "LEFT", 16, 0)
		Row.Name:SetText("Test")
		Row.Name:SetTextColor(1.0, 1.0, 1.0, 1.0)

		Row.Enabled = CreateFrame("CheckButton", nil, Row)
		Row.Enabled:SetPoint("RIGHT", Row, "RIGHT", -4, 0)
		Row.Enabled:SetWidth(16)
		Row.Enabled:SetHeight(16)
		Row.Enabled:SetScript("OnClick", function(this)
			if this:GetChecked() then
				this:SetChecked(true)
			else
				this:SetChecked(false)
			end
			me.Enabled[this.Key] = this:GetChecked()
			me:RefreshGraph()
		end)
		Row.Enabled:SetNormalTexture("Interface\\Buttons\\UI-CheckBox-Up")
		Row.Enabled:SetPushedTexture("Interface\\Buttons\\UI-CheckBox-Down")
		Row.Enabled:SetCheckedTexture("Interface\\Buttons\\UI-CheckBox-Check")
		Row.Enabled:SetHighlightTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
		Row.Enabled:SetChecked(true)

		Row:Hide()

		table.insert(theFrame.Rows, Row)
	end

	theFrame.ScrollBar1 = CreateFrame("SCROLLFRAME", "Recount_GraphWindow_ScrollBar1", theFrame, "FauxScrollFrameTemplate")
	theFrame.ScrollBar1:SetScript("OnVerticalScroll", function(self, offset)
		FauxScrollFrame_OnVerticalScroll(self, offset, 20, Recount.GraphRefreshData)
	end)
	theFrame.ScrollBar1:SetPoint("TOPLEFT", theFrame.Rows[1], "TOPLEFT")
	theFrame.ScrollBar1:SetPoint("BOTTOMRIGHT", theFrame.Rows[10], "BOTTOMRIGHT")
	Recount:SetupScrollbar("Recount_GraphWindow_ScrollBar1")

	theFrame.TimeLabels = CreateFrame("Frame", nil, theFrame)
	local Labels = theFrame.TimeLabels

	Labels:SetWidth(219)
	Labels:SetHeight(16)
	Labels:SetPoint("TOPLEFT", theFrame.Rows[10], "BOTTOMLEFT", 0, -2)

	Labels.Who = Labels:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	Labels.Who:SetPoint("LEFT", Labels, "LEFT", 0, 0)
	Labels.Who:SetText(L["Fought"])

	Labels.Start = Labels:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	Labels.Start:SetPoint("CENTER", Labels, "RIGHT", -80, 0)
	Labels.Start:SetText(L["Start"])

	Labels.End = Labels:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	Labels.End:SetPoint("RIGHT", Labels, "RIGHT", -15, 0)
	Labels.End:SetText(L["End"])

	theFrame.TimeRows = {}
	for i = 1, 10 do
		local Row = CreateFrame("Frame", nil, theFrame)
		Row:SetWidth(219)
		Row:SetHeight(16)
		Row:SetPoint("TOP", Labels, "BOTTOM", 0, -2 - 18 * (i - 1))
		Row.id = i
		Row:EnableMouse(true)
		Row:SetScript("OnMouseDown", function(this)
			me:SelectCombatTimes(this.id)
		end)
		Row:SetScript("OnEnter", function(this)
			this.Highlighted:Show()
		end)
		Row:SetScript("OnLeave", function(this)
			this.Highlighted:Hide()
		end)

		Row.Background = Row:CreateTexture(nil, "BACKGROUND")
		Row.Background:SetAllPoints(Row)
		Row.Background:SetColorTexture(1.0, 1.0, 0.0, 0.3)
		Row.Background:Hide()

		Row.Highlighted = Row:CreateTexture(nil, "BACKGROUND")
		Row.Highlighted:SetAllPoints(Row)
		Row.Highlighted:SetColorTexture(1.0, 0.0, 0.0, 0.3)
		Row.Highlighted:Hide()

		Row.Who = Row:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
		Row.Who:SetPoint("LEFT",Row,"LEFT",0, 0)
		Row.Who:SetText("Test")
		Row.Who:SetTextColor(1.0, 1.0, 1.0, 1.0)

		Row.Start = Row:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
		Row.Start:SetPoint("CENTER", Row, "RIGHT", -80, 0)
		Row.Start:SetText("12:12:50")
		Row.Start:SetTextColor(1.0, 1.0, 1.0, 1.0)

		Row.End = Row:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
		Row.End:SetPoint("RIGHT", Row, "RIGHT", 0, 0)
		Row.End:SetText("12:12:50")
		Row.End:SetTextColor(1.0, 1.0, 1.0, 1.0)

		--Row:Hide()

		table.insert(theFrame.TimeRows, Row)
	end

	theFrame.ScrollBar2 = CreateFrame("SCROLLFRAME", "Recount_GraphWindow_ScrollBar2", theFrame, "FauxScrollFrameTemplate")
	theFrame.ScrollBar2:SetScript("OnVerticalScroll", function(self, offset)
		FauxScrollFrame_OnVerticalScroll(self, offset, 20, Recount.GraphRefreshCombat)
	end)
	theFrame.ScrollBar2:SetPoint("TOPLEFT", theFrame.TimeRows[1], "TOPLEFT")
	theFrame.ScrollBar2:SetPoint("BOTTOMRIGHT", theFrame.TimeRows[10], "BOTTOMRIGHT")
	Recount:SetupScrollbar("Recount_GraphWindow_ScrollBar2")

	theFrame.CloseButton = CreateFrame("Button", nil, theFrame)
	theFrame.CloseButton:SetNormalTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Up")
	theFrame.CloseButton:SetPushedTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Down")
	theFrame.CloseButton:SetHighlightTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Highlight")
	theFrame.CloseButton:SetWidth(20)
	theFrame.CloseButton:SetHeight(20)
	theFrame.CloseButton:SetPoint("TOPRIGHT", theFrame, "TOPRIGHT", -4, -12)
	theFrame.CloseButton:SetScript("OnClick", function(this)
		this:GetParent():Hide()
	end)

	theFrame.RefreshButton = CreateFrame("Button", nil, theFrame)
	theFrame.RefreshButton:SetNormalTexture("Interface\\Buttons\\UI-RotationLeft-Button-Up")
	theFrame.RefreshButton:SetPushedTexture("Interface\\Buttons\\UI-RotationLeft-Button-Down")
	theFrame.RefreshButton:SetWidth(20)
	theFrame.RefreshButton:SetHeight(20)
	theFrame.RefreshButton:SetPoint("RIGHT", theFrame.CloseButton, "LEFT", 0, 0)
	theFrame.RefreshButton:SetScript("OnClick", function()
		me:RefreshGraph()
	end)

	theFrame.SelectAllButton = CreateFrame("Button",nil, theFrame)
	theFrame.SelectAllButton:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-Up")
	theFrame.SelectAllButton:SetPushedTexture("Interface\\Buttons\\UI-PlusButton-Down")
	theFrame.SelectAllButton:SetWidth(16)
	theFrame.SelectAllButton:SetHeight(16)
	theFrame.SelectAllButton:SetPoint("RIGHT", theFrame.RefreshButton, "LEFT", 0, 0)
	theFrame.SelectAllButton:SetScript("OnClick", function()
		Recount:AddAllToGraph()
	end)

	theFrame.Normalize = CreateFrame("Frame", nil, theFrame)
	local Normalize = theFrame.Normalize

	Normalize:SetWidth(80)
	Normalize:SetHeight(18)
	Normalize:SetPoint("BOTTOMRIGHT", theFrame, "BOTTOMRIGHT", -164, 2)

	Normalize.Text = Normalize:CreateFontString(nil,"OVERLAY","GameFontNormal")
	Normalize.Text:SetPoint("LEFT",Normalize,"LEFT",0, 0)
	Normalize.Text:SetText(L["Normalize"])

	Normalize.Enabled = CreateFrame("CheckButton", nil, Normalize)
	Normalize.Enabled:SetPoint("LEFT", Normalize.Text, "RIGHT", 6, 0)
	Normalize.Enabled:SetWidth(18)
	Normalize.Enabled:SetHeight(18)
	--Normalize.Enabled.id = CurRow
	Normalize.Enabled:SetScript("OnClick", function(this)
		if this:GetChecked() then
			this:SetChecked(true)
			theFrame.NormalizeOn = true
		else
			this:SetChecked(false)
			theFrame.NormalizeOn = false
		end
		me:RefreshGraph()
	end)
	Normalize.Enabled:SetNormalTexture("Interface\\Buttons\\UI-CheckBox-Up")
	Normalize.Enabled:SetPushedTexture("Interface\\Buttons\\UI-CheckBox-Down")
	Normalize.Enabled:SetCheckedTexture("Interface\\Buttons\\UI-CheckBox-Check")
	Normalize.Enabled:SetHighlightTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
	Normalize.Enabled:SetChecked(false)
	Normalize:Show()

	theFrame.Integrate = CreateFrame("Frame", nil, theFrame)
	local Integrate = theFrame.Integrate

	Integrate:SetWidth(80)
	Integrate:SetHeight(18)
	Integrate:SetPoint("BOTTOMRIGHT", theFrame, "BOTTOMRIGHT", -70, 2)

	Integrate.Text = Integrate:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	Integrate.Text:SetPoint("LEFT", Integrate, "LEFT", 0, 0)
	Integrate.Text:SetText(L["Integrate"])

	Integrate.Enabled = CreateFrame("CheckButton", nil, Integrate)
	Integrate.Enabled:SetPoint("LEFT", Integrate.Text, "RIGHT", 6, 0)
	Integrate.Enabled:SetWidth(18)
	Integrate.Enabled:SetHeight(18)
	--Integrate.Enabled.id = CurRow
	Integrate.Enabled:SetScript("OnClick", function(this)
		if this:GetChecked() then
			this:SetChecked(true)
			theFrame.IntegrateOn = true
		else
			this:SetChecked(false)
			theFrame.IntegrateOn = false
		end
		me:RefreshGraph()
	end)
	Integrate.Enabled:SetNormalTexture("Interface\\Buttons\\UI-CheckBox-Up")
	Integrate.Enabled:SetPushedTexture("Interface\\Buttons\\UI-CheckBox-Down")
	Integrate.Enabled:SetCheckedTexture("Interface\\Buttons\\UI-CheckBox-Check")
	Integrate.Enabled:SetHighlightTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
	Integrate.Enabled:SetChecked(false)
	Integrate:Show()

	theFrame.Stacked = CreateFrame("Frame", nil, theFrame)
	local Stacked = theFrame.Stacked

	Stacked:SetWidth(60)
	Stacked:SetHeight(18)
	Stacked:SetPoint("BOTTOMRIGHT", theFrame, "BOTTOMRIGHT", 0, 2)

	Stacked.Text = Integrate:CreateFontString(nil, "OVERLAY", "GameFontNormal")
	Stacked.Text:SetPoint("LEFT", Stacked, "LEFT", 0, 0)
	Stacked.Text:SetText(L["Stack"])

	Stacked.Enabled = CreateFrame("CheckButton", nil, Integrate)
	Stacked.Enabled:SetPoint("LEFT", Stacked.Text, "RIGHT", 6, 0)
	Stacked.Enabled:SetWidth(18)
	Stacked.Enabled:SetHeight(18)
	--Stacked.Enabled.id = CurRow
	Stacked.Enabled:SetScript("OnClick",function(this)
		if this:GetChecked() then
			this:SetChecked(true)
			theFrame.StackedOn = true
		else
			this:SetChecked(false)
			theFrame.StackedOn = false
		end
		me:RefreshGraph()
	end)
	Stacked.Enabled:SetNormalTexture("Interface\\Buttons\\UI-CheckBox-Up")
	Stacked.Enabled:SetPushedTexture("Interface\\Buttons\\UI-CheckBox-Down")
	Stacked.Enabled:SetCheckedTexture("Interface\\Buttons\\UI-CheckBox-Check")
	Stacked.Enabled:SetHighlightTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
	Stacked.Enabled:SetChecked(false)
	Stacked:Show()

	theFrame.NormalizeOn = false
	theFrame.IntegrateOn = false
	theFrame.StackedOn = false

	theFrame:Hide()
end
