local L = AceLibrary("AceLocale-2.2"):new("FuBar_PerformanceFu")
local Tablet = AceLibrary("Tablet-2.0")
local Abacus = AceLibrary("Abacus-2.0")
local Crayon = AceLibrary("Crayon-2.0")

PerformanceFu = AceLibrary("AceAddon-2.0"):new("FuBarPlugin-2.0", "AceConsole-2.0", "AceEvent-2.0", "AceDB-2.0")

PerformanceFu.version = "2.0" .. string.sub("$Revision: 18728 $", 12, -3)
PerformanceFu.date = string.sub("$Date: 2006-12-03 12:04:37 -0500 (Sun, 03 Dec 2006) $", 8, 17)
PerformanceFu.hasIcon = true

local string_format = string.format
local table_concat = table.concat
local table_insert = table.insert

PerformanceFu:RegisterDB("PerformanceFuDB")
PerformanceFu:RegisterDefaults("profile", {
	showFramerate = true,
	showLatency = false,
	showMemory = true,
	showRate = false,
})

function PerformanceFu:IsShowingFramerate()
	return self.db.profile.showFramerate
end

function PerformanceFu:ToggleShowingFramerate()
	self.db.profile.showFramerate = not self.db.profile.showFramerate
	self:Update()
end

function PerformanceFu:IsShowingLatency()
	return self.db.profile.showLatency
end

function PerformanceFu:ToggleShowingLatency()
	self.db.profile.showLatency = not self.db.profile.showLatency
	self:Update()
end

function PerformanceFu:IsShowingRate()
	return self.db.profile.showRate
end

function PerformanceFu:ToggleShowingRate()
	self.db.profile.showRate = not self.db.profile.showRate
	self:Update()
end

function PerformanceFu:IsShowingMemory()
	return self.db.profile.showMemory
end

function PerformanceFu:ToggleShowingMemory()
	self.db.profile.showMemory = not self.db.profile.showMemory
	self:Update()
end

local initialMemory, currentMemory
local mem1, mem2, mem3, mem4, mem5, mem6, mem7, mem8, mem9, mem10
local timeSinceLastUpdate
local justEntered
local gcTime

function PerformanceFu:OnEnable()
	initialMemory = collectgarbage('count')
	currentMemory = initialMemory
	mem1 = currentMemory
	mem2 = currentMemory
	mem3 = currentMemory
	mem4 = currentMemory
	mem5 = currentMemory
	mem6 = currentMemory
	mem7 = currentMemory
	mem8 = currentMemory
	mem9 = currentMemory
	mem10 = currentMemory
	timeSinceLastUpdate = 0
	justEntered = true
	gcTime = time()
	self:ScheduleRepeatingEvent(self.OnUpdate, 1, self)
end

local options = {
	type = 'group',
	args = {
		framerate = {
			type = 'toggle',
			name = L["Show framerate"],
			desc = L["Toggle whether to framerate"],
			get = "IsShowingFramerate",
			set = "ToggleShowingFramerate",
		},
		latency = {
			type = 'toggle',
			name = L["Show latency"],
			desc = L["Toggle whether to latency (lag)"],
			get = "IsShowingLatency",
			set = "ToggleShowingLatency",
		},
		memory = {
			type = 'toggle',
			name = L["Show memory usage"],
			desc = L["Toggle whether to show current memory usage"],
			get = "IsShowingMemory",
			set = "ToggleShowingMemory",
		},
		rate = {
			type = 'toggle',
			name = L["Show rate of increasing memory usage"],
			desc = L["Toggle whether to show increasing rate of memory"],
			get = "IsShowingRate",
			set = "ToggleShowingRate",
		},
		forcegc = {
			type = 'execute',
			name = L["Force garbage collection"],
			desc = L["Force a garbage collection to happen"],
			order = 101,
			func = collectgarbage
		}
	}
}
PerformanceFu:RegisterChatCommand(L["AceConsole-options"], options)
PerformanceFu.OnMenuRequest = options

function PerformanceFu:OnUpdate()
	if justEntered then
		if not timeSinceLastUpdate then
			timeSinceLastUpdate = 0
		end
		timeSinceLastUpdate = timeSinceLastUpdate + 1
		if timeSinceLastUpdate >= 10 then
			initialMemory = collectgarbage('count')
			currentMemory = initialMemory
			mem1 = currentMemory
			mem2 = currentMemory
			mem3 = currentMemory
			mem4 = currentMemory
			mem5 = currentMemory
			mem6 = currentMemory
			mem7 = currentMemory
			mem8 = currentMemory
			mem9 = currentMemory
			mem10 = currentMemory
			timeSinceLastUpdate = nil
			justEntered = false
		end
	else
		local t = time()
		timeSinceLastUpdate = 0
		mem1, mem2, mem3, mem4, mem5, mem6, mem7, mem8, mem9, mem10 =
			currentMemory, mem1, mem2, mem3, mem4, mem5, mem6, mem7, mem8, mem9
		currentMemory = collectgarbage('count')
		self:Update()
	end
end

local t = {}
function PerformanceFu:OnTextUpdate()
	if not mem10 then
		mem10 = currentMemory
	end
	local currentRate = (currentMemory - mem10) / 10

	if self:IsShowingFramerate() then
		local framerate = floor(GetFramerate() + 0.5)
		table_insert(t, format("|cff%s%d|r fps", Crayon:GetThresholdHexColor(framerate / 60), framerate))
	end
	if self:IsShowingLatency() then
		local _,_,latency = GetNetStats()
		table_insert(t, format("|cff%s%d|r ms", Crayon:GetThresholdHexColor(latency, 1000, 500, 250, 100, 0), latency))
	end
	if self:IsShowingMemory() then
		table_insert(t, format("|cff%s%.1f|r MiB", Crayon:GetThresholdHexColor(currentMemory, 51200, 40960, 30520, 20480, 10240), currentMemory / 1024))
	end
	if self:IsShowingRate() then
		table_insert(t, format("|cff%s%.1f|r KiB/s", Crayon:GetThresholdHexColor(currentRate, 30, 10, 3, 1, 0), currentRate))
	end
	self:SetText(table_concat(t, " "))
	local num = table.getn(t)
	for i = 1, num do
		t[i] = nil
	end
end

function PerformanceFu:OnTooltipUpdate()
	local cat = Tablet:AddCategory(
		'columns', 2,
		'child_textR', 1,
		'child_textG', 1,
		'child_textB', 0
	)
	local framerate = GetFramerate()
	local r, g, b = Crayon:GetThresholdColor(framerate / 60)
	cat:AddLine(
		'text', L["Framerate:"],
		'text2', string_format("%.1f fps", framerate),
		'text2R', r,
		'text2G', g,
		'text2B', b
	)

	cat = Tablet:AddCategory(
		'text', L["Network status"],
		'columns', 2,
		'child_textR', 1,
		'child_textG', 1,
		'child_textB', 0,
		'child_text2R', 1,
		'child_text2G', 1,
		'child_text2B', 1
	)
	local bandwidthIn, bandwidthOut, latency = GetNetStats()
	bandwidthIn, bandwidthOut = bandwidthIn * 1024, bandwidthOut * 1024
	local r, g, b = Crayon:GetThresholdColor(latency, 3000, 1000, 250, 100, 0)
	cat:AddLine(
		'text', L["Latency:"],
		'text2', string_format("%d ms", latency),
		'text2R', r,
		'text2G', g,
		'text2B', b
	)

	cat:AddLine(
		'text', L["Bandwidth in:"],
		'text2', string_format("%d B/s", bandwidthIn)
	)

	cat:AddLine(
		'text', L["Bandwidth out:"],
		'text2', string_format("%d B/s", bandwidthOut)
	)

	local averageRate = (currentMemory - initialMemory) / (time() - gcTime)
	cat = Tablet:AddCategory(
		'text', L["Memory usage"],
		'columns', 2,
		'child_textR', 1,
		'child_textG', 1,
		'child_textB', 0,
		'child_text2R', 1,
		'child_text2G', 1,
		'child_text2B', 1
	)
	local currentRate = (currentMemory - mem10) / 10

	local r, g, b = Crayon:GetThresholdColor(currentMemory, 51200, 40960, 30520, 20480, 10240)
	cat:AddLine(
		'text', L["Current memory:"],
		'text2', string_format("%.1f MiB", currentMemory / 1024),
		'text2R', r,
		'text2G', g,
		'text2B', b
	)

	r, g, b = Crayon:GetThresholdColor(initialMemory, 51200, 40960, 30520, 20480, 10240)
	cat:AddLine(
		'text', L["Initial memory:"],
		'text2', string_format("%.1f MiB", initialMemory / 1024),
		'text2R', r,
		'text2G', g,
		'text2B', b
	)

	r, g, b = Crayon:GetThresholdColor(currentRate, 30, 10, 3, 1, 0)
	cat:AddLine(
		'text', L["Increasing rate:"],
		'text2', string_format("%.1f KiB/s", currentRate),
		'text2R', r,
		'text2G', g,
		'text2B', b
	)

	r, g, b = Crayon:GetThresholdColor(averageRate, 30, 10, 3, 1, 0)
	cat:AddLine(
		'text', L["Average increasing rate:"],
		'text2', format("%.1f KiB/s", averageRate),
		'text2R', r,
		'text2G', g,
		'text2B', b
	)
end
