-- --------------------
-- TellMeWhen
-- Originally by NephMakes

-- Other contributions by:
--		Sweetmms of Blackrock, Oozebull of Twisting Nether, Oodyboo of Mug'thol,
--		Banjankri of Blackrock, Predeter of Proudmoore, Xenyr of Aszune

-- Currently maintained by
-- Cybeloras of Aerie Peak
-- --------------------


if not TMW then return end

local TMW = TMW
local print = TMW.print
local L = TMW.L
local LSM = LibStub("LibSharedMedia-3.0")
local _, pclass = UnitClass("Player")
local UnitPower, UnitPowerMax =
	  UnitPower, UnitPowerMax

local UnitPowerMissing = UnitPowerMissing or function(unit, powerType)
	return UnitPowerMax(unit, powerType) - UnitPower(unit, powerType)
end

local issecretvalue = TMW.issecretvalue
local pairs, wipe, _G =
	  pairs, wipe, _G
local PowerBarColor = PowerBarColor

local defaultPowerTypes = {
	ROGUE		= Enum.PowerType.Energy,
	PRIEST		= Enum.PowerType.Mana,
	DRUID		= Enum.PowerType.Mana,
	WARRIOR		= Enum.PowerType.Rage,
	MAGE		= Enum.PowerType.Mana,
	WARLOCK		= Enum.PowerType.Mana,
	PALADIN		= Enum.PowerType.Mana,
	SHAMAN		= Enum.PowerType.Mana,
	HUNTER		= Enum.PowerType.Focus,
	DEATHKNIGHT = Enum.PowerType.RunicPower,
	MONK 		= Enum.PowerType.Energy,
	DEMONHUNTER = Enum.PowerType.Fury,
	EVOKER		= Enum.PowerType.Mana,
}
local defaultPowerType = defaultPowerTypes[pclass]

local PBarsToUpdate = {}

local PowerBar = TMW:NewClass("IconModule_PowerBar", "IconModule", "UpdateTableManager", "AceEvent-3.0", "AceTimer-3.0")
PowerBar:UpdateTable_Set(PBarsToUpdate)

PowerBar:RegisterAnchorableFrame("PowerBar")

function PowerBar:OnNewInstance(icon)
	local bar = CreateFrame("StatusBar", self:GetChildNameBase() .. "PowerBar", icon)
	self.bar = bar
	
	self.texture = bar:CreateTexture(nil, "OVERLAY")
	self.texture:SetAllPoints()
	bar:SetStatusBarTexture(self.texture)
	
	local colorinfo = PowerBarColor[defaultPowerType]
	if not colorinfo then
		error("No PowerBarColor was found for class " .. pclass .. "! Is the defaultPowerType for the class not defined?")
	end
	bar:SetStatusBarColor(colorinfo.r, colorinfo.g, colorinfo.b, 0.9)
	self.powerType = defaultPowerType
	
	self.Min = 0
	self.Max = 1
	bar:SetMinMaxValues(self.Min, self.Max)
	
	self.Offset = 0
end

function PowerBar:OnEnable()
	local icon = self.icon
	local attributes = icon.attributes
	
	self.bar:Show()
	local texture = icon.group.TextureName
	if texture == "" then
		texture = TMW.db.profile.TextureName
	end
	self.texture:SetTexture(LSM:Fetch("statusbar", texture))
	
	self:SPELL(icon, attributes.spell)
end
function PowerBar:OnDisable()
	self.bar:Hide()
	self:UpdateTable_Unregister()
end

function PowerBar:OnUsed()
	PowerBar:RegisterEvent("SPELL_UPDATE_USABLE")
	PowerBar:RegisterEvent("UNIT_POWER_FREQUENT")
end
function PowerBar:OnUnused()
	PowerBar:UnregisterEvent("SPELL_UPDATE_USABLE")
	PowerBar:UnregisterEvent("UNIT_POWER_FREQUENT")
end


function PowerBar:SetSpell(spell)
	local bar = self.bar
	self.spell = spell
	
	if spell then
		self:UpdateCost()

		self:UpdateTable_Register()
		
		self:Update()

	-- Removes the bar from the update table. True is returned if it was in there.
	elseif self:UpdateTable_Unregister() then
		local value = self.Invert and self.Max or 0
		bar:SetValue(value)
		self.__value = value
		
		self:UpdateTable_Unregister()
	end
end

local wowMajor = TMW.wowMajor

function PowerBar:UpdateCost()
	local bar = self.bar
	local spell = self.spell
	
	if spell then
		local cost, costData = TMW.GetSpellCost(spell)
		
		if cost then
			local powerType = costData.type

			if wowMajor <= 9 then
				-- holy power hack: always use a max of 3 to account for variable cost spenders.
				-- This version check might not be right. Not sure when this was added, nor when it was removed.
				cost = powerType == (Enum.PowerType.HolyPower) and 3 or cost or 0 
			end

			self.__value = nil -- the displayed value might change when we change the max, so force an update
			
			if not self.Invert then
				local max = UnitPowerMax("player", powerType) - self.Offset
				local min = max - cost
				self.Min = min
				self.Max = max
				bar:SetMinMaxValues(min, max)
			else
				local min = 0
				local max = cost - self.Offset
				self.Min = min
				self.Max = max
				bar:SetMinMaxValues(min, max)
			end
		
			powerType = powerType or defaultPowerType
			if powerType ~= self.powerType then
				local colorinfo = PowerBarColor[powerType] or PowerBarColor[defaultPowerType]
				
				bar:SetStatusBarColor(colorinfo.r, colorinfo.g, colorinfo.b, 0.9)
				self.powerType = powerType
			end

			self:Update()
		end
	end
end

function PowerBar:Update(power, missing, powerTypeNum)
	local bar = self.bar

	powerTypeNum = powerTypeNum or self.powerType
	
	if powerTypeNum == self.powerType then
		local value

		if not self.Invert then
			value = missing or UnitPowerMissing("player", powerTypeNum)
		else
			value = power or UnitPower("player", powerTypeNum)
		end

		if issecretvalue(value) then
			bar:SetValue(value)
		else
			local Max = self.Max
			local Min = self.Min

			if value > Max then
				value = Max
			elseif value < Min then
				value = Min
			end

			if self.__value ~= value then
				bar:SetValue(value)
				self.__value = value
			end
		end
	end
end


function PowerBar:SPELL_UPDATE_USABLE()
	if TMW.Locked then
		for i = 1, #PBarsToUpdate do
			local Module = PBarsToUpdate[i]
			Module:UpdateCost()
		end
	end
end

function PowerBar:UNIT_POWER_FREQUENT(event, unit, powerType)
	if unit == "player" then
		local powerTypeNum = powerType and _G["SPELL_POWER_" .. powerType]
		local power = powerTypeNum and UnitPower("player", powerTypeNum)
		local missing = powerTypeNum and UnitPowerMissing("player", powerTypeNum)
		
		for i = 1, #PBarsToUpdate do
			local Module = PBarsToUpdate[i]
			Module:Update(power, missing, powerTypeNum)
		end
	end
end


function PowerBar:SPELL(icon, spellChecked)
	self:SetSpell(spellChecked)
end
PowerBar:SetDataListener("SPELL")


TMW:RegisterCallback("TMW_LOCK_TOGGLED", function(event, Locked)
	if not Locked then
		PowerBar:UpdateTable_UnregisterAll()
	end
end)

