
KLHTM_Release = 15
KLHTM_Revision = 21
KLHTM_Build = 177

-- build 6 is final for release 1
-- build 11 is final for release 2
-- build 30 is final for release 3
-- build 32 is final for release 4
-- build 44 is final for release 5
-- build 54 is final for release 6
-- build 73 is final for release 7
-- build 80 is final for release 8
-- build 92 is final for release 9
-- build 103 is final for release 10
-- build 116 is final for release 11
-- build 124 is final for release 12
-- build 141 is final for release 13
-- build 156 is final for release 14

function KLHTM_Startup()

	KLHTM_InitialiseData()	-- KLHThreatMeterData.lua
	KLHTM_RegisterEvents()
	KLHTM_LocaliseConsoleIO() -- KLHThreatMeterLocalisation.lua
	KLHTM_ConsoleIOStartup() -- KLHThreatMeterConsoleIO.lua
	KLHTM_ResetTimingData()
	
	-- Console Commands
	SLASH_KLHThreatMeter1 = "/klhtm"
	SLASH_KLHThreatMeter2 = "/ktm"
	SLASH_KLHThreatMeter3 = "/klhthreatmeter"
	SlashCmdList["KLHThreatMeter"] = KLHTM_ConsoleCommand
	
	KLHTM_Print(string.format(KLHTM_String("print", "main", "startupmessage"), KLHTM_Release, KLHTM_Revision), nil, true)

end

function KLHTM_RegisterEvents()
	
	-- to determine when sunder armor fails
	this:RegisterEvent("CHAT_MSG_SPELL_FAILED_LOCALPLAYER")
	
	-- damage events
	this:RegisterEvent("CHAT_MSG_COMBAT_SELF_HITS")
	this:RegisterEvent("CHAT_MSG_SPELL_SELF_DAMAGE")
	this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE")
	this:RegisterEvent("CHAT_MSG_SPELL_DAMAGESHIELDS_ON_SELF")
	
	-- healing events
	this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS")
	this:RegisterEvent("CHAT_MSG_SPELL_SELF_BUFF")

	-- more healing
	this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS")

	-- for network messages
	this:RegisterEvent("CHAT_MSG_CHANNEL")

	-- this is to detect AFK
	this:RegisterEvent("CHAT_MSG_SYSTEM")
	
	-- death is an aggro wipe, too!
	this:RegisterEvent("CHAT_MSG_COMBAT_FRIENDLY_DEATH")
	
	-- knockbacks
	this:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE")
	
	-- onyxia phase 3
	this:RegisterEvent("CHAT_MSG_MONSTER_YELL")
	
	-- razorgore phase 2
	this:RegisterEvent("CHAT_MSG_MONSTER_EMOTE")
	
	-- /chatinfo callback
	this:RegisterEvent("CHAT_MSG_CHANNEL_LIST")
	
	-- debuffed
	this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE")
	
	-- buff / debuff fade
	this:RegisterEvent("CHAT_MSG_SPELL_AURA_GONE_SELF")
		
end


------------------------------------
--        Timing Functions        --
------------------------------------

KLHTM_ThisSecondStart = 0
KLHTM_OriginalStartTime = 0
KLHTM_TimingData = nil

KLHTM_Updates = {"Data", "Gui", "Alert", "Net", "Main", "Targetting"}
KLHTM_Events = {"Combat", "Net"}
		
function KLHTM_ResetTimingData()
	
	KLHTM_ThisSecondStart = GetTime()
	KLHTM_OriginalStartTime = KLHTM_ThisSecondStart
	
	KLHTM_TimingData = 
	{		
		["Events"] = KLHTM_NewTimingData(),
		["Updates"] = KLHTM_NewTimingData(),
		["Total"] = KLHTM_NewTimingData(),
	}
	
	local value
	
	for _, value in KLHTM_Updates do
		KLHTM_TimingData[value .. "Update"] = KLHTM_NewTimingData()
	end
	
	for _, value in KLHTM_Events do
		KLHTM_TimingData[value .. "Event"] = KLHTM_NewTimingData()
	end
	
end

function KLHTM_NewTimingData()
	
	return
	{
		["Total"] = 0,
		["BackTrack"] = {}, -- key = 1, 2, 3, etc for last, second last, etc. Values are converted to milliseconds per second
		["BackTrackLength"] = 5,
		["Current"] = 0, -- total ms in this period
		["RecordSequence"] = 0, -- max time over the length of the backtrack
	}

end

-- return: milliseconds taken, as a float
function KLHTM_TimeFunction(Function, Name)
	
	local start = debugprofilestop()
	Function()
	local stop = debugprofilestop()
	
	local out = stop - start
	if out > 100 or out < 0 then
		KLHTM_PrintTrace("TimingDebug", string.format("Dubious timing data from %s: %d (= %d - %d).", Name, out, stop, start))
		return 0
	end
	
	return out
end

function KLHTM_MainOnUpdate()

	-- Check if we have broken into a new second
	local timenow = GetTime()
	if timenow > KLHTM_ThisSecondStart + 1.0 then
		
		-- 1) Get the length of the last interval, and start the new interval
		local duration = timenow - KLHTM_ThisSecondStart
		KLHTM_ThisSecondStart = timenow
		
		-- 2) Shuffle the previous intervals back
		local value
		local x
		
		for _, value in KLHTM_TimingData do -- Value is a TimingData structure
			
			for x = value.BackTrackLength, 2, -1 do
				if value.BackTrack[x - 1] then
					value.BackTrack[x] = value.BackTrack[x - 1]
				end
			end
		end
		
		-- 3) put the new time interval in backtrack 1
		local total
		local thisvalue
		
		-- a) Events
		total = 0
		
		for _, value in KLHTM_Events do
			thisvalue = KLHTM_TimingData[value .. "Event"].Current / duration
			KLHTM_TimingData[value .. "Event"].Current = 0
			
			KLHTM_TimingData[value .. "Event"].BackTrack[1] = thisvalue
			total = total + thisvalue
		end
		
		KLHTM_TimingData["Events"].BackTrack[1] = total
		
		-- b) Updates
		total = 0
		
		for _, value in KLHTM_Updates do
			thisvalue = KLHTM_TimingData[value .. "Update"].Current / duration
			KLHTM_TimingData[value .. "Update"].Current = 0
			
			KLHTM_TimingData[value .. "Update"].BackTrack[1] = thisvalue
			total = total + thisvalue
		end
		
		KLHTM_TimingData["Updates"].BackTrack[1] = total
		
		-- c) Total
		KLHTM_TimingData["Total"].BackTrack[1] = KLHTM_TimingData["Updates"].BackTrack[1] + KLHTM_TimingData["Events"].BackTrack[1]
		
		-- 4) Update Record and Total
		for _, value in KLHTM_TimingData do -- Value is a TimingData structure
			
			-- a) Total
			value.Total = value.Total + value.BackTrack[1]
			
			-- b) Record
			total = 0
			
			for x = 1, value.BackTrackLength do
				if value.BackTrack[x] then
					total = total + value.BackTrack[x]
				else
					break
				end
			end
			
			if total > value.RecordSequence then 
				value.RecordSequence = total
			end
		end
		
	end
end

function KLHTM_OnUpdate()
	
	local value
	local nextfunction
	local timetaken
	
	if KLHTM_IsLoaded == false then
		return
	end
	
	for _, value in KLHTM_Updates do
		nextfunction = getglobal("KLHTM_" .. value .. "OnUpdate")
		
		timetaken = KLHTM_TimeFunction(nextfunction, value .. "Update")
		KLHTM_TimingData[value .. "Update"].Current = KLHTM_TimingData[value .. "Update"].Current + timetaken
	end
	
end

function KLHTM_OnEvent()

	-- This bit is one-off
	if event == "VARIABLES_LOADED" then
		KLHTM_StartupAfterVariablesLoaded()
	end
	
	if KLHTM_IsLoaded == false then
		return
	end

	local value
	local nextfunction
	local timetaken
	
	for _, value in KLHTM_Events do
		nextfunction = getglobal("KLHTM_" .. value .. "OnEvent")
		
		timetaken = KLHTM_TimeFunction(nextfunction, value .. "Event")
		KLHTM_TimingData[value .. "Event"].Current = KLHTM_TimingData[value .. "Event"].Current + timetaken
	end
	
end


------------------------------------
--        Helper Functions        --
------------------------------------


function KLHTM_Announce(message)
		
	local channel = "SAY"

	if GetNumRaidMembers() > 0 then
		channel = "RAID"

	elseif GetNumPartyMembers() > 0 then
		channel = "PARTY"
	end

	SendChatMessage(message, channel)

end

-- takes: number. returns: string. Gets the first decimal place if applicable.
function KLHTM_FormatDecimal(value)

	if floor(value) == value then
		return string.format("%d", value)

	else
		local base = string.format("%f", value)
		local dotpoint = string.find(base, "%.")
		return string.sub(base, 1, dotpoint + 1)
	end
end


function KLHTM_GetHashTableLength(Table)
	local length = 0
	for key, value in Table do
		length = length + 1
	end
	return length
end
