local CooldownType = {
	New = function(self)
		local o = {}
		setmetatable(o, self)
		self.__index = self
		return o
	end,
}

local NullType = CooldownType:New()
NullType.GetActiveInfo = function(self) return false, 0, 0 end
local TotemType = CooldownType:New()
TotemType.GetActiveInfo = function(self)
	for i = 1, 4 do
		local present, name, start, duration = GetTotemInfo(i)
		if present and name == self.name then return true, start, duration end
	end
	return false, 0, 0
end

local Cooldown = {
	New = function(self, type, spellid, keybind)
		local o = {
			["type"] = type,
			["spellid"] = spellid,
			["name"] = GetSpellInfo(spellid),
			["icon"] = GetSpellTexture(spellid),
			["keybind"] = keybind,
		}
		setmetatable(o, self)
		self.__index = self
		return o
	end,

	GetCooldownInfo = function(self)
		local start, duration = GetSpellCooldown(self.spellid)
		return start > 0 and duration > aura_env.gcdThreshold, start, duration
	end,

	GetActiveInfo = function(self) return self.type:GetActiveInfo() end,
}

aura_env.cooldowns = {
	[5394] = Cooldown:New(TotemType, 5394, "C"), -- Healing Stream Totem
	[2484] = Cooldown:New(TotemType, 2484, "SY"), -- Earthbind Totem
	[8143] = Cooldown:New(TotemType, 8143, "S5"), -- Tremor Totem
	[8177] = Cooldown:New(TotemType, 8177, "5"), -- Grounding Totem
	[108273] = Cooldown:New(TotemType, 108273, "S4"), -- Windwalk Totem
	[108270] = Cooldown:New(TotemType, 108270, "SF"), -- Stone Bulwark Totem
}
aura_env.gcdThreshold = 1.5

aura_env.Update = function(allstates, cd)
	local state = allstates[cd.spellid] or {}

	state.IsOnCooldown = cd:GetCooldownInfo()
	state.IsActive = cd:GetActiveInfo()
	state.Keybind = cd.keybind

	if state.IsOnCooldown and not state.IsActive then
		local _, start, duration = cd:GetCooldownInfo()
		state.progressType = "timed"
		state.duration = duration
		state.expirationTime = start + duration
	elseif state.IsOnCooldown and state.IsActive then
		local _, start, duration = cd:GetActiveInfo()
		state.progressType = "timed"
		state.duration = duration
		state.expirationTime = start + duration
	end

	state.changed = true
	state.show = true
	state.name = cd.name
	state.icon = cd.icon
	state.spellid = cd.spellid
	allstates[cd.spellid] = state
end

aura_env.UpdateAll = function(allstates)
	for _, v in pairs(aura_env.cooldowns) do
		aura_env.Update(allstates, v)
	end
end

aura_env.HandleEvent = function(allstates)
	-- TODO: Handle events better
	-- On cooldown begin -> trigger update on relevant spell
	-- On totem die -> same
	-- On buff remove
	-- On debuff remove
	-- On... Whatever else might happen
	aura_env.UpdateAll(allstates)
end
