if not ShockAndAwe then return end

local L = LibStub("AceLocale-3.0"):GetLocale("ShockAndAwe")
local media = LibStub:GetLibrary("LibSharedMedia-3.0");
local C = ShockAndAwe.constants -- Defined in ShockAndAwe LUA no locale needed.

ShockAndAwe.UptimeFrame = CreateFrame("Frame", "SAA_UptimeFrame", UIParent)

---------------------------
-- Uptime functions
---------------------------

function ShockAndAwe:InitialiseUptime()
	self.uptime = {}
	self.uptime = {
		session = {},
		lastfight = {},
		incombat = false,
		TimerEvent = nil,
		currentTime = nil,
	}
	self:InitialiseUptimeBuffs(self.uptime.session)
	self:InitialiseUptimeBuffs(self.uptime.lastfight)
end

function ShockAndAwe:InitialiseUptimeBuffs(timeframe)
	timeframe.totalTime = 0
	if not timeframe.buffs then
		timeframe.buffs = {}
	end
	if not timeframe.buffs[C["Elemental Devastation"]] then
		timeframe.buffs[C["Elemental Devastation"]] = {}
		timeframe.buffs[C["Elemental Devastation"]].name = C["Elemental Devastation"]
		timeframe.buffs[C["Elemental Devastation"]].icon = C["Elemental Devastation Icon"]
	end
	if not timeframe.buffs[C["Flurry"]] then
		timeframe.buffs[C["Flurry"]] = {}
		timeframe.buffs[C["Flurry"]].name = C["Flurry"]
		timeframe.buffs[C["Flurry"]].icon = C["Flurry Icon"]
	end
	timeframe.buffs[C["Elemental Devastation"]].uptime = 0
	timeframe.buffs[C["Flurry"]].uptime = 0
end

function ShockAndAwe:UpdateUptime()
	if not self.uptime.incombat then
		return
	end
	local currentTime = GetTime()
	-- add conditional safety measure - we should never have no current time but to be sure...
	if  not self.uptime.currentTime then
		self.uptime.currentTime = currentTime
	end
	local diffTime = currentTime - self.uptime.currentTime
	
	self.uptime.session.totalTime = self.uptime.session.totalTime + diffTime;
	self.uptime.lastfight.totalTime = self.uptime.lastfight.totalTime + diffTime;
	
	local i = 1
	local buff = UnitBuff("player", i)
	while buff do
		if self.uptime.session.buffs[buff] then
			self.uptime.session.buffs[buff].uptime = self.uptime.session.buffs[buff].uptime + diffTime
		end
		if self.uptime.lastfight.buffs[buff] then
			self.uptime.lastfight.buffs[buff].uptime = self.uptime.lastfight.buffs[buff].uptime + diffTime
		end		
		i = i + 1
		buff = UnitBuff("player", i)
	end	
	self.uptime.currentTime = currentTime
	self:UpdateUptimeFrames(false)
end

function ShockAndAwe:CreateUptimeFrame()
	self.UptimeFrame:ClearAllPoints()
	self.UptimeFrame:SetScale(self.db.char.uptime.scale)
	self.UptimeFrame:SetFrameStrata("BACKGROUND")
	self.UptimeFrame:SetWidth(self.db.char.uptime.fWidth + self.db.char.uptime.barHeight)
	self.UptimeFrame:SetHeight(self.db.char.uptime.fHeight + 16)
	self.UptimeFrame:SetBackdrop(self.frameBackdrop)
	self.UptimeFrame:SetBackdropColor(0, 0, 0, self.db.char.uptime.alpha)
	self.UptimeFrame:SetMovable(true)
	self.UptimeFrame:RegisterForDrag("LeftButton")
	self.UptimeFrame:SetPoint(self.db.char.uptime.point, self.db.char.uptime.relativeTo, self.db.char.uptime.relativePoint, self.db.char.uptime.xOffset, self.db.char.uptime.yOffset)
	self.UptimeFrame:SetScript("OnDragStart", 
		function()
			self.UptimeFrame:StartMoving();
		end );
	self.UptimeFrame:SetScript("OnDragStop",
		function()
			self.UptimeFrame:StopMovingOrSizing();
			self.UptimeFrame:SetScript("OnUpdate", nil);
			self:FinishedMoving(self.db.char.uptime, self.UptimeFrame);
		end );
	
	local barfont = media:Fetch("font", self.db.char.barfont)
	if not self.UptimeFrame.topText then
		self.UptimeFrame.topText = self.UptimeFrame:CreateFontString(nil, "OVERLAY")
	end
	self.UptimeFrame.topText:SetTextColor(1,1,1,1)
	self.UptimeFrame.topText:SetFont(barfont, self.db.char.barfontsize, self.db.char.barfonteffect)
	self.UptimeFrame.topText:SetPoint("TOP", self.UptimeFrame, "TOP", 0, - 2)
	self.UptimeFrame.topText:SetText(L["uptime_session"])
	
	if not self.UptimeFrame.ResetButton then
		self.UptimeFrame.ResetButton=CreateFrame("Button", nil, self.UptimeFrame)
	end
	local size = self.UptimeFrame.topText:GetHeight()
	self.UptimeFrame.ResetButton:SetNormalTexture("Interface\\Addons\\ShockAndAwe\\textures\\icon-reset")
	self.UptimeFrame.ResetButton:SetHighlightTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Highlight.blp")
	self.UptimeFrame.ResetButton:SetWidth(size)
	self.UptimeFrame.ResetButton:SetHeight(size)
	self.UptimeFrame.ResetButton:SetPoint("TOPRIGHT", self.UptimeFrame.topText, "TOPLEFT", -5, 0)
	self.UptimeFrame.ResetButton:SetScript("OnClick",function() ShockAndAwe:ResetUptimeValues() end)
	self.UptimeFrame.ResetButton:SetFrameLevel(self.UptimeFrame.ResetButton:GetFrameLevel()+1)
	self.UptimeFrame.ResetButton:SetScript("OnEnter", function() UptimeResetButtonTooltip() end);
	self.UptimeFrame.ResetButton:SetScript("OnLeave", function() GameTooltip:Hide() end);


	local baseOffset = (-1 * self.db.char.uptime.fHeight / 6) - 2 -- 6 bars + top line + middle line 
	if not self.UptimeFrame.middleText then
		self.UptimeFrame.middleText = self.UptimeFrame:CreateFontString(nil, "OVERLAY")
	end
	self.UptimeFrame.middleText:SetTextColor(1,1,1,1)
	self.UptimeFrame.middleText:SetFont(barfont, self.db.char.barfontsize, self.db.char.barfonteffect)
	self.UptimeFrame.middleText:SetPoint("TOP", self.UptimeFrame, "TOP", 0, 3 * baseOffset - 2)
	self.UptimeFrame.middleText:SetText(L["uptime_lastfight"])
	if self.db.char.uptime.show then
		self.UptimeFrame:Show()
	else
		self.UptimeFrame:Hide()
	end
	local session = self.uptime.session
	local lastfight = self.uptime.lastfight
	
	self:CreateUptimeBarFrame(session.buffs[C["Flurry"]], self.db.char.uptime.flurry, baseOffset)
	self:CreateUptimeBarFrame(session.buffs[C["Elemental Devastation"]], self.db.char.uptime.ed, 2 * baseOffset)
	
	self:CreateUptimeBarFrame(lastfight.buffs[C["Flurry"]], self.db.char.uptime.flurry, 4 * baseOffset)
	self:CreateUptimeBarFrame(lastfight.buffs[C["Elemental Devastation"]], self.db.char.uptime.ed, 5 * baseOffset)
end

function ShockAndAwe:CreateUptimeBarFrame(buff, buffColours, frameOffset)
	if not buff.barFrame then
		buff.barFrame = CreateFrame("Frame", nil, self.UptimeFrame)
	end
	buff.barFrame:SetFrameStrata("LOW")
	buff.barFrame:SetWidth(self.db.char.uptime.barWidth + self.db.char.uptime.barHeight)
	buff.barFrame:SetHeight(self.db.char.uptime.barHeight)
	buff.barFrame:ClearAllPoints()
	buff.barFrame:SetPoint("TOPLEFT", self.UptimeFrame, "TOPLEFT", self.db.char.uptime.barHeight, frameOffset)
	buff.barFrame:SetScript("OnUpdate", function() self:UpdateUptimeFrames(false); end );
	
	if not buff.barFrame.buffIcon then
		buff.barFrame.buffIcon = CreateFrame("Frame", nil, buff.barFrame)
	end
	buff.barFrame.buffIcon:SetWidth(self.db.char.uptime.barHeight)
	buff.barFrame.buffIcon:SetHeight(self.db.char.uptime.barHeight)
	buff.barFrame.buffIcon:SetBackdrop({ bgFile = buff.icon })
	buff.barFrame.buffIcon:SetPoint("TOPRIGHT", buff.barFrame, "TOPLEFT", 12, 0)
	
	if not buff.barFrame.statusbar then
		buff.barFrame.statusbar = CreateFrame("StatusBar", nil, buff.barFrame, "TextStatusBar")
	end
	buff.barFrame.statusbar:ClearAllPoints()
	buff.barFrame.statusbar:SetHeight(self.db.char.uptime.barHeight)
	buff.barFrame.statusbar:SetWidth(self.db.char.uptime.barWidth)
	buff.barFrame.statusbar:SetPoint("RIGHT", buff.barFrame, "RIGHT")
	buff.barFrame.statusbar:SetStatusBarTexture(media:Fetch("statusbar", self.db.char.texture))
	buff.barFrame.statusbar:SetStatusBarColor(buffColours.r, buffColours.g, buffColours.b, buffColours.a)
	buff.barFrame.statusbar:SetMinMaxValues(0,1)
	buff.barFrame.statusbar:SetValue(0)
	
	local barfont = media:Fetch("font", self.db.char.barfont)
	if not buff.barFrame.statusbar.leftText then
		buff.barFrame.statusbar.leftText = buff.barFrame.statusbar:CreateFontString(nil, "OVERLAY")
	end
	buff.barFrame.statusbar.leftText:SetTextColor(1,1,1,1)
	buff.barFrame.statusbar.leftText:SetFont(barfont, self.db.char.barfontsize, self.db.char.barfonteffect)
	buff.barFrame.statusbar.leftText:SetPoint("TOPLEFT", buff.barFrame.statusbar, "TOPLEFT")
	buff.barFrame.statusbar.leftText:SetText("0.0s")
	
	if not buff.barFrame.statusbar.rightText then
		buff.barFrame.statusbar.rightText = buff.barFrame.statusbar:CreateFontString(nil, "OVERLAY")
	end
	buff.barFrame.statusbar.rightText:SetTextColor(1,1,1,1)
	buff.barFrame.statusbar.rightText:SetFont(barfont, self.db.char.barfontsize, self.db.char.barfonteffect)
	buff.barFrame.statusbar.rightText:SetPoint("TOPRIGHT", buff.barFrame.statusbar, "TOPRIGHT")
	buff.barFrame.statusbar.rightText:SetText("0%")
	
	buff.barFrame.statusbar:SetScript("OnEnter", function() UptimeStatusBarTooltip(buff) end);
	buff.barFrame.statusbar:SetScript("OnLeave", function() GameTooltip:Hide() end);
	buff.barFrame.buffIcon:SetScript("OnEnter", function() UptimeStatusBarTooltip(buff) end);
	buff.barFrame.buffIcon:SetScript("OnLeave", function() GameTooltip:Hide() end);
end

function UptimeStatusBarTooltip(buff)
	if not InCombatLockdown() then
		GameTooltip:SetOwner(buff.barFrame, "ANCHOR_BOTTOMLEFT");
		GameTooltip:AddLine(buff.name)
		GameTooltip:AddTexture(buff.icon)
		GameTooltip:AddLine((L["Uptime is %s (%s)"]):format(
				buff.barFrame.statusbar.leftText:GetText(),
				buff.barFrame.statusbar.rightText:GetText()
			))
		GameTooltip:Show()
	else
		GameTooltip:Hide()
	end
end

function UptimeResetButtonTooltip()
	if not InCombatLockdown() then
		GameTooltip:SetOwner(ShockAndAwe.UptimeFrame.ResetButton, "ANCHOR_BOTTOMLEFT");
		GameTooltip:AddLine(L["Reset Session statistics"])
		GameTooltip:Show()
	else
		GameTooltip:Hide()
		
	end
end

function ShockAndAwe:UpdateUptimeFrames(forceUpdate)
	if InCombatLockdown() or forceUpdate then
		local session = self.uptime.session
		local lastfight = self.uptime.lastfight
		session.buffs[C["Flurry"]].barFrame.statusbar.leftText:SetText(self:DurationString(session.buffs[C["Flurry"]].uptime))
		session.buffs[C["Elemental Devastation"]].barFrame.statusbar.leftText:SetText(self:DurationString(session.buffs[C["Elemental Devastation"]].uptime))
		lastfight.buffs[C["Flurry"]].barFrame.statusbar.leftText:SetText(self:DurationString(lastfight.buffs[C["Flurry"]].uptime))
		lastfight.buffs[C["Elemental Devastation"]].barFrame.statusbar.leftText:SetText(self:DurationString(lastfight.buffs[C["Elemental Devastation"]].uptime))

		local percent
		if session.totalTime == 0 then
			session.buffs[C["Flurry"]].barFrame.statusbar:SetValue(0)
			session.buffs[C["Flurry"]].barFrame.statusbar.rightText:SetText("0%")
			session.buffs[C["Elemental Devastation"]].barFrame.statusbar:SetValue(0)
			session.buffs[C["Elemental Devastation"]].barFrame.statusbar.rightText:SetText("0%")
		else
			percent = session.buffs[C["Flurry"]].uptime / session.totalTime
			session.buffs[C["Flurry"]].barFrame.statusbar:SetValue(percent)
			session.buffs[C["Flurry"]].barFrame.statusbar.rightText:SetText((("%d"):format(percent * 100)) .. "%")
		
			percent = session.buffs[C["Elemental Devastation"]].uptime / session.totalTime
			session.buffs[C["Elemental Devastation"]].barFrame.statusbar:SetValue(percent)
			session.buffs[C["Elemental Devastation"]].barFrame.statusbar.rightText:SetText((("%d"):format(percent * 100)) .. "%")
		end

		if lastfight.totalTime == 0 then
			lastfight.buffs[C["Flurry"]].barFrame.statusbar:SetValue(0)
			lastfight.buffs[C["Flurry"]].barFrame.statusbar.rightText:SetText("0%")
			lastfight.buffs[C["Elemental Devastation"]].barFrame.statusbar:SetValue(0)
			lastfight.buffs[C["Elemental Devastation"]].barFrame.statusbar.rightText:SetText("0%")
		else
			percent = lastfight.buffs[C["Flurry"]].uptime / lastfight.totalTime
			lastfight.buffs[C["Flurry"]].barFrame.statusbar:SetValue(percent)
			lastfight.buffs[C["Flurry"]].barFrame.statusbar.rightText:SetText((("%d"):format(percent * 100)) .. "%")
			
			percent = lastfight.buffs[C["Elemental Devastation"]].uptime / lastfight.totalTime
			lastfight.buffs[C["Elemental Devastation"]].barFrame.statusbar:SetValue(percent)
			lastfight.buffs[C["Elemental Devastation"]].barFrame.statusbar.rightText:SetText((("%d"):format(percent * 100)) .. "%")
		end
	end
end

function ShockAndAwe:ResetUptime()
	self.UptimeFrame:ClearAllPoints()
	self.db.char.uptime.point = self.defaults.char.uptime.point
	self.db.char.uptime.relativeTo = self.defaults.char.uptime.relativeTo 
	self.db.char.uptime.relativePoint = self.defaults.char.uptime.relativePoint
	self.db.char.uptime.xOffset = self.defaults.char.uptime.xOffset
	self.db.char.uptime.yOffset = self.defaults.char.uptime.yOffset
	self.db.char.uptime.fWidth = self.defaults.char.uptime.fWidth
	self.db.char.uptime.fHeight = self.defaults.char.uptime.fHeight
	self.db.char.uptime.scale = self.defaults.char.uptime.scale
	self:CreateUptimeFrame()
	self:Print(L["uptime_reset"])
end

function ShockAndAwe:ResetUptimeValues()
	self:InitialiseUptimeBuffs(self.uptime.session)
	self:InitialiseUptimeBuffs(self.uptime.lastfight)
	self:UpdateUptimeFrames(true)
end