--[[
    MiniPerfsFu!
        "ONOES DISCORD IS ATEING AL MEH SOFTDRIVE ROFLMAOAFK!!!!!"

    Based on PerformanceFu
--]]

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

local tablet = AceLibrary("Tablet-2.0")
local dewdrop = AceLibrary("Dewdrop-2.0")
local abacus = LibStub("LibAbacus-3.0")
local crayon = AceLibrary("Crayon-2.0")

MiniPerfsFu:RegisterDB("MiniPerfsFuDB")

MiniPerfsFu.hasIcon = true

local floor = math.floor
local GetFramerate = GetFramerate
local GetNetStats = GetNetStats
local collectgarbage = collectgarbage
local time = time
local gcinfo = gcinfo
local concat = table.concat

local L = { -- L for Locals!
    OTHERMEMORYINFO = "Other Memory Info",
    INITIALMEMORY = "Initial Memory:",
    AVERAGEINCREASINGRATE = "Average Increasing Rate:",
    GARBAGECOLLECTTHRESHOLD = "Garbage Collect Threshold:",
    TIMETONEXTGARBAGECOLLECT = "Time to Next Garbage Collect:",
    HINT = "Click to run the garbage collector",
}


function MiniPerfsFu:AddConfigToggle(text, varName)
    dewdrop:AddLine(
        'text', text,
        'func', function()
		   self.db.profile[varName] = not self.db.profile[varName]
        end,
        'checked', self.db.profile[varName]
    )
end

function MiniPerfsFu:OnMenuRequest()
   self:AddConfigToggle("Show FPS", "showFps")
   self:AddConfigToggle("Show Latency", "showLatency")
   self:AddConfigToggle("Show Memory Rate", "showMemRate")
   self:AddConfigToggle("Show Memory Use", "showMemUse")
   self:AddConfigToggle("Short Text", "shortText")
end

-- Choo choo! Here comes the local train!
local initialMemory, gcThreshold, currentMemory, mem1, mem2, mem3, mem4, mem5, mem6, mem7, mem8, mem9, mem10, timeSinceLastUpdate, gcTime, justEntered

function MiniPerfsFu:OnInitialize()
    local profile = self.db.profile
    -- Set the default to be all on
    if profile.showFps == nil then
        profile.showFps     = 1
        profile.showLatency = 1
        profile.showMemRate = 1
        profile.showMemUse  = 1
    end


    initialMemory, gcThreshold = gcinfo()
    currentMemory = initialMemory
    mem1 = currentMemory
    mem2 = currentMemory
    mem3 = currentMemory
    mem4 = currentMemory
    mem5 = currentMemory
    mem6 = currentMemory
    mem7 = currentMemory
    mem8 = currentMemory
    mem9 = currentMemory
    mem10 = currentMemory
    timeSinceLastUpdate = 0
    gcTime = time()
    justEntered = true
end

function MiniPerfsFu:OnEnable()
    self:ScheduleRepeatingEvent(self.OnUpdate, 1, self)
end

function MiniPerfsFu:OnClick()
    collectgarbage()
end

function MiniPerfsFu:OnUpdate(difference)
	if justEntered == true then
		timeSinceLastUpdate = (timeSinceLastUpdate or 0) + 1
		if timeSinceLastUpdate >= 10 then
			initialMemory, gcThreshold = gcinfo()
			currentMemory = initialMemory
			mem1 = currentMemory
			mem2 = currentMemory
			mem3 = currentMemory
			mem4 = currentMemory
			mem5 = currentMemory
			mem6 = currentMemory
			mem7 = currentMemory
			mem8 = currentMemory
			mem9 = currentMemory
			mem10 = currentMemory
			timeSinceLastUpdate = nil
			gcTime = time()
			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, gcThreshold = gcinfo()
		if mem1 > currentMemory then
			initialMemory = currentMemory
			gcTime = t
			mem10, mem9, mem9, mem8, mem7, mem6, mem5, mem4, mem3, mem2, mem1 = currentMemory, currentMemory, currentMemory, currentMemory, currentMemory, currentMemory, currentMemory, currentMemory, currentMemory, currentMemory
		end

		self:Update()
	end
end

local tmp, count
local sep, shortText = " ", false
local tbl = {}
local format = string.format

function MiniPerfsFu:OnTextUpdate()
    local profile = self.db.profile
    count = 0   
    if shortText ~= profile.shortText then
       shortText = profile.shortText
       sep = shortText and "/" or " "
    end

    mem10 = mem10 or currentMemory

    if profile.showFps then
        tmp = floor(GetFramerate() + 0.5)
	count = 1
        tbl[1] = format(shortText and "|cff%s%d|r" or "|cff%s%d|r fps", crayon:GetThresholdHexColor(tmp / 60), tmp)
    end
   
    if profile.showLatency then
        _,_,tmp = GetNetStats()
	count = count + 1
        tbl[count] = format(shortText and "|cff%s%d|r" or "|cff%s%d|r ms", crayon:GetThresholdHexColor(tmp, 1000, 500, 250, 100, 0), tmp)
    end

    if profile.showMemUse then
	count = count + 1
        tbl[count] = format(shortText and "|cff%s%.1f|r" or "|cff%s%.1f|r MiB", crayon:GetThresholdHexColor(currentMemory, 51200, 40960, 30520, 20480, 10240), currentMemory / 1024)
   end

    if profile.showMemRate then
       tmp = (currentMemory - mem10) / 10
       count = count + 1
       tbl[count] = format(shortText and "|cff%s%.1f|r" or "|cff%s%.1f|r KiB/s", crayon:GetThresholdHexColor(tmp, 30, 10, 3, 1, 0), tmp)
    end	 

    self:SetText(count and concat(tbl, sep) or "MiniPerfsFu")

    for i = 1, count do tbl[i] = nil  end
end

function MiniPerfsFu:OnTooltipUpdate()
    local cat = tablet:AddCategory(
        'text', L.OTHERMEMORYINFO,
		'columns', 2,
		'child_textR', 1,
		'child_textG', 1,
		'child_textB', 0
	)

	if initialMemory then
		local r, g, b = crayon:GetThresholdColor(initialMemory, 51200, 40960, 30520, 20480, 10240)
		cat:AddLine(
			'text', L.INITIALMEMORY,
			'text2', string.format("%.1f MiB", initialMemory / 1024),
			'text2R', r,
			'text2G', g,
			'text2B', b
		)
	end

	local averageRate = nil
	if currentMemory and initialMemory then
		averageRate = (currentMemory - initialMemory) / (time() - gcTime)
		r, g, b = crayon:GetThresholdColor(averageRate, 30, 10, 3, 1, 0)
		cat:AddLine(
			'text', L.AVERAGEINCREASINGRATE,
			'text2', string.format("%.1f KiB/s", averageRate),
			'text2R', r,
			'text2G', g,
			'text2B', b
		)
	end

	if gcThreshold then
		r, g, b = crayon:GetThresholdColor(gcThreshold, 51200, 40960, 30520, 20480, 10240)
		cat:AddLine(
			'text', L.GARBAGECOLLECTTHRESHOLD,
			'text2', string.format("%.1f MiB", gcThreshold / 1024),
			'text2R', r,
			'text2G', g,
			'text2B', b
		)
	end

	if gcThreshold and currentMemory then
		local totalSecs = (gcThreshold - currentMemory) / averageRate
		local timeToNext = abacus:FormatDurationFull(totalSecs)
		r, g, b = crayon:GetThresholdColor(totalSecs, 0, 900, 1800, 2700, 3600)
		cat:AddLine(
			'text', L.TIMETONEXTGARBAGECOLLECT,
			'text2', timeToNext,
			'text2R', r,
			'text2G', g,
			'text2B', b
		)
	end
    
    tablet:SetHint(L.HINT)
end
