local surface = AceLibrary("Surface-1.0");
local L = AceLibrary("AceLocale-2.2"):new("CooldownTimers");

local bars = nil
local tooltip = nil
local anchors = nil

local options = {
	type = 'group',
	args = {
		maxtime = {
			type = 'text',
			name = L["Max Time"],
			desc = L["Set the max time for a cooldown to be tracked."],
			get = function()
				return CooldownTimers.db.char.maxtime;
			end,
			set = function(s)
				CooldownTimers.db.char.maxtime = tonumber(s);
			end,
			validate = function(s)
				return type(tonumber(s)) == "number";
			end,
			usage = "<time>",
		},
		mintime = {
			type = 'text',
			name = L["Min Time"],
			desc = L["Set the min time for a cooldown to be tracked."],
			get = function()
				return CooldownTimers.db.char.mintime;
			end,
			set = function(s)
				CooldownTimers.db.char.mintime = tonumber(s);
			end,
			validate = function(s)
				return type(tonumber(s)) == "number";
			end,
			usage = "<time>",
		},
		fixgroups = {
			type = 'execute',
			name = L["Fix Groups"],
			desc = L["Fix skills that have groups that no longer exist (moving them to groups that do exist)."],
			func = function()
				CooldownTimers:FixGroups();
			end,
		},
		menu = {
			type = 'execute',
			name = L["Show Menu"],
			desc = L["Shows the configuration menu"],
			func = function()
				CooldownTimers:OpenMenu();
			end,
		},
	},
};

CooldownTimers = AceLibrary("AceAddon-2.0"):new("AceConsole-2.0", "AceEvent-2.0", "AceDB-2.0", "CandyBar-2.0", "FuBarPlugin-2.0");
local CooldownTimers = CooldownTimers

function CooldownTimers:OnInitialize()
	self:RegisterChatCommand({"/cooldowntimers", "/cdt"}, options);
	self:RegisterDB("CooldownTimersDB", "CooldownTimersDBPC");
	self:RegisterDefaults("char", {
		["groups"] = {
			["CDT"] = {
			},
			["ItemCooldowns"] = {
			},
			
		},
		["announce"] = {
			x = 0,
			y = 0,
			point = "CENTER",
			relPoint = "CENTER",
			announceString = "%s ready!",
			scale = 1,
			fade = 1,
			enabled = true,
		},
		["barOptions"] = {
			["colors"] = { "blue", "green", "red", },
			["fade"] = 1,
			["barwidth"] = 200,
			["barheight"] = 16,
			["bargap"] = 0,
			["columns"] = 1,
			["scale"] = 1,
			["up"] = false,
			["collapse"] = true,
			["announce"] = true,
			["texture"] = "Interface\\TargetingFrame\\UI-StatusBar",
		},
		["cooldowns"] = {},
		["maxtime"] = 120,
		["mintime"] = 1.5,
		["skillgroups"] = {
			[L["Freezing Trap"] ] = L["Traps"],
			[L["Frost Trap"] ] = L["Traps"],
			[L["Immolation Trap"] ] = L["Traps"],
			[L["Snake Trap"] ] = L["Traps"],
			[L["Explosive Trap"] ] = L["Traps"],
			[L["Frost Shock"] ] = L["Shocks"],
			[L["Flame Shock"] ] = L["Shocks"],
			[L["Earth Shock"] ] = L["Shocks"],
		},
		["itemgroups"] = {
			[L["Bethor's Potion"] ] = L["Potions"],
			[L["Combat Healing Potion"] ] = L["Potions"],
			[L["Combat Mana Potion"] ] = L["Potions"],
			[L["Discolored Healing Potion"] ] = L["Potions"],
			[L["Dreamless Sleep Potion"] ] = L["Potions"],
			[L["Fire Protection Potion"] ] = L["Potions"],
			[L["Free Action Potion"] ] = L["Potions"],
			[L["Frost Protection Potion"] ] = L["Potions"],
			[L["Great Rage Potion"] ] = L["Potions"],
			[L["Greater Arcane Protection Potion"] ] = L["Potions"],
			[L["Greater Dreamless Sleep Potion"] ] = L["Potions"],
			[L["Greater Fire Protection Potion"] ] = L["Potions"],
			[L["Greater Frost Protection Potion"] ] = L["Potions"],
			[L["Greater Healing Potion"] ] = L["Potions"],
			[L["Greater Mana Potion"] ] = L["Potions"],
			[L["Greater Nature Protection Potion"] ] = L["Potions"],
			[L["Greater Shadow Protection Potion"] ] = L["Potions"],
			[L["Greater Stoneshield Potion"] ] = L["Potions"],
			[L["Healing Potion"] ] = L["Potions"],
			[L["Holy Protection Potion"] ] = L["Potions"],
			[L["Holy Spring Water"] ] = L["Potions"],
			[L["Invisibility Potion"] ] = L["Potions"],
			[L["Jungle Remedy"] ] = L["Potions"],
			[L["Lesser Healing Potion"] ] = L["Potions"],
			[L["Lesser Invisibility Potion"] ] = L["Potions"],
			[L["Lesser Mana Potion"] ] = L["Potions"],
			[L["Lesser Stoneshield Potion"] ] = L["Potions"],
			[L["Light of Elune"] ] = L["Potions"],
			[L["Limited Invulnerability Potion"] ] = L["Potions"],
			[L["Living Action Potion"] ] = L["Potions"],
			[L["Living Action Potion"] ] = L["Potions"],
			[L["Magic Resistance Potion"] ] = L["Potions"],
			[L["Major Healing Draught"] ] = L["Potions"],
			[L["Major Healing Potion"] ] = L["Potions"],
			[L["Major Mana Draught"] ] = L["Potions"],
			[L["Major Mana Potion"] ] = L["Potions"],
			[L["Major Rejuvenation Potion"] ] = L["Potions"],
			[L["Mana Potion"] ] = L["Potions"],
			[L["Mighty Rage Potion"] ] = L["Potions"],
			[L["Minor Healing Potion"] ] = L["Potions"],
			[L["Minor Magic Resistance Potion"] ] = L["Potions"],
			[L["Minor Mana Potion"] ] = L["Potions"],
			[L["Minor Rejuvenation Potion"] ] = L["Potions"],
			[L["Mug of Shimmer Stout"] ] = L["Potions"],
			[L["Nature Protection Potion"] ] = L["Potions"],
			[L["Purification Potion"] ] = L["Potions"],
			[L["Rage Potion"] ] = L["Potions"],
			[L["Restorative Potion"] ] = L["Potions"],
			[L["Shadow Protection Potion"] ] = L["Potions"],
			[L["Superior Healing Draught"] ] = L["Potions"],
			[L["Superior Healing Potion"] ] = L["Potions"],
			[L["Superior Mana Draught"] ] = L["Potions"],
			[L["Superior Mana Potion"] ] = L["Potions"],
			[L["Swiftness Potion"] ] = L["Potions"],
			[L["Swim Speed Potion"] ] = L["Potions"],
			[L["Wildvine Potion"] ] = L["Potions"],
			[L["Shadow Protection Potion"] ] = L["Potions"],
			[L["Cinder Bracers"] ] = L["Explosives"],
			[L["Clutch of Foresight"] ] = L["Explosives"],
			[L["Dog Whistle"] ] = L["Explosives"],
			[L["Mechanical Greench"] ] = L["Explosives"],
			[L["Mechanical Yeti"] ] = L["Explosives"],
			[L["Wail of the Banshee"] ] = L["Explosives"],
			[L["Arcane Bomb"] ] = L["Explosives"],
			[L["Bag of Marbles"] ] = L["Explosives"],
			[L["Big Bronze Bomb"] ] = L["Explosives"],
			[L["Big Iron Bomb"] ] = L["Explosives"],
			[L["Coarse Dynamite"] ] = L["Explosives"],
			[L["Compact Harvest Reaper Kit"] ] = L["Explosives"],
			[L["Crystal Charge"] ] = L["Explosives"],
			[L["Crystal Yield"] ] = L["Explosives"],
			[L["Dark Iron Bomb"] ] = L["Explosives"],
			[L["Dense Dynamite"] ] = L["Explosives"],
			[L["Discombobulator Ray"] ] = L["Explosives"],
			[L["Explosive Rocket"] ] = L["Explosives"],
			[L["Explosive Sheep"] ] = L["Explosives"],
			[L["Ez-Thro Dynamite"] ] = L["Explosives"],
			[L["Ez-Thro Dynamite II"] ] = L["Explosives"],
			[L["Flash Bundle"] ] = L["Explosives"],
			[L["Glowing Cat Figurine"] ] = L["Explosives"],
			[L["Glowing Wax Stick"] ] = L["Explosives"],
			[L["Gnomish Flame Turret"] ] = L["Explosives"],
			[L["Goblin Fishing Pole"] ] = L["Explosives"],
			[L["Goblin Land Mine"] ] = L["Explosives"],
			[L["Goblin Sapper Charge"] ] = L["Explosives"],
			[L["Heavy Dynamite"] ] = L["Explosives"],
			[L["Hi-Explosive Bomb"] ] = L["Explosives"],
			[L["Iron Grenade"] ] = L["Explosives"],
			[L["Large Copper Bomb"] ] = L["Explosives"],
			[L["Large Rope Net"] ] = L["Explosives"],
			[L["M73 Frag Grenade"] ] = L["Explosives"],
			[L["Magic Candle"] ] = L["Explosives"],
			[L["Magic Dust"] ] = L["Explosives"],
			[L["Mithril Frag Bomb"] ] = L["Explosives"],
			[L["Netherweave Net"] ] = L["Explosives"],
			[L["Portable Bronze Mortar"] ] = L["Explosives"],
			[L["Really Sticky Glue"] ] = L["Explosives"],
			[L["Rough Copper Bomb"] ] = L["Explosives"],
			[L["Rough Dynamite"] ] = L["Explosives"],
			[L["Severed Voodoo Claw"] ] = L["Explosives"],
			[L["Slumber Sand"] ] = L["Explosives"],
			[L["Small Bronze Bomb"] ] = L["Explosives"],
			[L["Solid Dynamite"] ] = L["Explosives"],
			[L["Stratholme Holy Water"] ] = L["Explosives"],
			[L["Super Sapper Charge"] ] = L["Explosives"],
			[L["The Big One"] ] = L["Explosives"],
			[L["The Bigger One"] ] = L["Explosives"],
			[L["Thorium Grenade"] ] = L["Explosives"],
			[L["Flash Bomb"] ] = L["Explosives"],
		},
		["itemcooldowns"] = {},
		["petcooldowns"] = {},
	});
end

function CooldownTimers:OnEnable()
	self:RegisterEvent("SPELL_UPDATE_COOLDOWN");
	self:RegisterEvent("PLAYER_ALIVE", "PopulateCooldowns");
	self:RegisterEvent("SPELLS_CHANGED", "PopulateCooldowns");
	self:RegisterEvent("PLAYER_ENTERING_WORLD", "ResetCooldowns");
	self:RegisterEvent("BAG_UPDATE_COOLDOWN");
	self:RegisterEvent("UNIT_PET");
	
	tooltip = CreateFrame("GameTooltip", "CDTTooltip", UIParent, "GameTooltipTemplate");
	tooltip:SetScript("OnLoad", function()
		this:SetOwner(UIparent, "ANCHOR_NONE");
	end );
	tooltip:SetOwner(UIParent, "ANCHOR_NONE");
	anchors = {};
	for k,v in pairs(self.db.char.groups) do
		self:MakeAnchor(k,v);
	end
	self:FixGroups();
	
	surface:Register("Blizzard Default", "Interface\\TargetingFrame\\UI-StatusBar")
	surface:Register("Smooth", "Interface\\AddOns\\CooldownTimers2\\Textures\\smooth.tga")
	surface:Register("Cilo", "Interface\\AddOns\\CooldownTimers2\\Textures\\cilo.tga")
	surface:Register("BantoBar", "Interface\\AddOns\\CooldownTimers2\\Textures\\bar.tga")
	
	if not bars then
		bars = {};
	end
	
	if not self.announce then
		self:MakeAnnounce();
	end
end

function CooldownTimers:ResetCooldowns()
	self:KillAllBars();
	for k,v in pairs(self.db.char.cooldowns) do
		v.start = 0;
	end
	for k,v in pairs(self.db.char.petcooldowns) do
		v.start = 0;
	end
	for k,v in pairs(self.db.char.itemcooldowns) do
		v.start = 0;
	end
	self:SPELL_UPDATE_COOLDOWN();
	self:BAG_UPDATE_COOLDOWN();
	if UnitExists("pet") then
		self:PET_BAR_UPDATE_COOLDOWN();
	end
end

function CooldownTimers:MakeAnchor(group, info)
	if info.disabled then return; end
	anchors[group] = CreateFrame("Frame",group..tostring(math.floor(GetTime())),UIParent)
	anchors[group]:ClearAllPoints();
	anchors[group]:SetBackdrop( {
		bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
		edgeFile="Interface\\Tooltips\\UI-Tooltip-Border",
		tile = true, tileSize = 16, edgeSize = 16, insets = {
			left = 5, right = 5, top = 5, bottom = 5 },
	} );
	if not info.x then
		info.x = 0;
		info.y = 0;
		info.relPoint = "CENTER";
		info.point = "CENTER";
	end
	anchors[group]:SetWidth(128)
	anchors[group]:SetHeight(30)
	anchors[group]:SetBackdropColor(0.1,0.1,0.3);
	anchors[group]:EnableMouse(true);
	anchors[group]:SetPoint(info.point, "UIParent", info.relPoint, info.x, info.y);
	local msg = anchors[group]:CreateFontString(nil,"overlay","GameFontNormal");
	msg:ClearAllPoints();
	msg:SetPoint("center", anchors[group], "center");
	msg:SetText(group);
	anchors[group]:SetMovable(true);
	anchors[group]:SetScript("OnDragStart", function() anchors[group]:StartMoving(); GameTooltip:Hide() end);
	anchors[group]:SetScript("OnDragStop", function() anchors[group]:StopMovingOrSizing(); self:SavePosition(group) end);
	anchors[group]:SetScript("OnMouseUp", function() self:OnAnchorClick(group) end);
	anchors[group]:SetScript("OnEnter", function() self:ShowAnchorTooltip() end);
	anchors[group]:SetScript("OnLeave", function() GameTooltip:Hide() end);
	anchors[group]:RegisterForDrag("LeftButton");
	if self.db.char.groups[group].locked then
		anchors[group]:Hide();
	else
		anchors[group]:Show();
	end
	self:RegisterCandyBarGroup(group);
	self:SetCandyBarGroupPoint(group, "TOP", anchors[group]:GetName(), "BOTTOM", 0, 0);
	self:SetCandyBarGroupGrowth(group, info.up or self.db.char.barOptions.up);
end

function CooldownTimers:MakeAnnounce()
	self.announce = {};
	self.announce.anchor = CreateFrame("Frame",nil,UIParent)
	self.announce.anchor:ClearAllPoints();
	self.announce.anchor:SetBackdrop( {
		bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
		edgeFile="Interface\\Tooltips\\UI-Tooltip-Border",
		tile = true, tileSize = 16, edgeSize = 16, insets = {
			left = 5, right = 5, top = 5, bottom = 5 },
	} );
	self.announce.anchor:SetWidth(30)
	self.announce.anchor:SetHeight(30)
	self.announce.anchor:SetBackdropColor(0.1,0.1,0.3);
	self.announce.anchor:EnableMouse(true);
	self.announce.anchor:SetPoint(self.db.char.announce.point, UIParent, self.db.char.announce.relPoint, self.db.char.announce.x, self.db.char.announce.y);
	self.announce.anchor:SetMovable(true);
	self.announce.anchor:SetScript("OnDragStart", function() self.announce.anchor:StartMoving(); GameTooltip:Hide() end);
	self.announce.anchor:SetScript("OnDragStop", function() self.announce.anchor:StopMovingOrSizing(); 
		self.db.char.announce.point, _, self.db.char.announce.relPoint, self.db.char.announce.x, self.db.char.announce.y = self.announce.anchor:GetPoint();
	end );
	self.announce.anchor:SetScript("OnEnter", function()
		GameTooltip:SetOwner(this, "ANCHOR_BOTTOMRIGHT");
		GameTooltip:AddLine("CDT Announce Anchor");
		GameTooltip:AddLine("Drag this to reposition");
		GameTooltip:AddLine("the announcement text.");
		GameTooltip:AddLine("Shift+Click this to lock it in position.");
		GameTooltip:Show();
	end);
	self.announce.anchor:SetScript("OnLeave", function() GameTooltip:Hide() end);
	self.announce.anchor:SetScript("OnMouseUp", function()
		if IsShiftKeyDown() then
			self.announce.anchor:Hide();
			self.db.char.announce.locked = true;
		end
	end);
	self.announce.anchor:RegisterForDrag("LeftButton");
	
	self.announce.frame = CreateFrame("Frame",nil,UIParent);
	self.announce.text = self.announce.frame:CreateFontString(nil,"OVERLAY", "ZoneTextFont");
	self.announce.frame:ClearAllPoints();
	self.announce.frame:SetAllPoints(self.announce.text);
	self.announce.text:ClearAllPoints();
	self.announce.text:SetPoint("CENTER", self.announce.anchor, "CENTER", 0,0);
	self.announce.text:SetText(self.db.char.announce.announceString);
	self.announce.frame:SetScale(self.db.char.announce.scale);
	self.announce.last = GetTime();
	self.announce.alpha = 1;
	self.announce.frame:SetScript("OnUpdate", function()
		if self.announce.anchor:IsShown() then return; end
		if (GetTime() - self.announce.last) > self.db.char.announce.fade then
			self.announce.alpha = self.announce.alpha - 0.1;
		end
		self.announce.frame:SetAlpha(self.announce.alpha);
		if self.announce.alpha <= 0 then
			self.announce.frame:Hide();
		end
	end );
	self.announce.text:Show();
	self.announce.frame:SetFrameStrata("BACKGROUND");
	
	if not self.db.char.announce.locked and self.db.char.announce.enabled then
		self.announce.anchor:Show();
		self.announce.frame:Show();
	else
		self.announce.anchor:Hide();
		self.announce.frame:Hide();
	end
end

function CooldownTimers:LockAnchor(group)
	self.db.char.groups[group].locked = true;
	anchors[group]:Hide();
end

function CooldownTimers:ShowAnchorTooltip()
	GameTooltip:SetOwner(this, "ANCHOR_BOTTOMRIGHT");
	GameTooltip:AddLine("CDT Group Anchor");
	GameTooltip:AddLine("Drag this to reposition");
	GameTooltip:AddLine("Shift+Left Click to hide");
	GameTooltip:AddLine("Alt+Left Click to show a test bar");
	GameTooltip:AddLine("Alt+Left Click again to hide the test bar");
	GameTooltip:AddLine("If you hide this, you can show it again by going to Group Options -> groupname -> Uncheck Lock");
	GameTooltip:Show();
end

function CooldownTimers:OnAnchorClick(group, altkey)
	if IsAltKeyDown() or altkey then
		if self:IsCandyBarRegistered(group.."testbar") then
			self:StopCandyBar(group.."testbar");
			return;
		end
		self:RegisterCandyBar(group.."testbar", 300, "Test bar", "Interface\\Icons\\INV_Misc_QuestionMark", unpack(self.db.char.barOptions.colors) );
		self:RegisterCandyBarWithGroup(group.."testbar", group);
		self:SetCandyBarTexture(group.."testbar", surface:Fetch(self.db.char.groups[group].texture or self.db.char.barOptions.texture));
		self:SetCandyBarWidth(group.."testbar", self.db.char.groups[group].barwidth or self.db.char.barOptions.barwidth);
		self:SetCandyBarHeight(group.."testbar", self.db.char.groups[group].barheight or self.db.char.barOptions.barheight);
		self:SetCandyBarScale(group.."testbar", self.db.char.groups[group].scale or self.db.char.barOptions.scale);
		self:StartCandyBar(group.."testbar", true);
	end
	if IsShiftKeyDown() then
		self:LockAnchor(group);
		return;
	end
end

function CooldownTimers:SavePosition(group)
	self.db.char.groups[group].point, _, self.db.char.groups[group].relPoint, self.db.char.groups[group].x, self.db.char.groups[group].y = anchors[group]:GetPoint();
end

function CooldownTimers:SPELL_UPDATE_COOLDOWN()
	local start, duration, enable, name;
	for k, v in pairs(self.db.char.cooldowns) do
		name = GetSpellName(v.id, BOOKTYPE_SPELL);
		if not v.disabled and (k == name or k == self.db.char.skillgroups[name]) then
			start, duration, enable = GetSpellCooldown(v.id, BOOKTYPE_SPELL);
			if enable == 1 and duration > self.db.char.mintime and duration <= self.db.char.maxtime and v.start ~= start then
				v.start = start;
				self:SetUpBar(k, v, duration);
			end
		end
	end
end

function CooldownTimers:BAG_UPDATE_COOLDOWN()
	local slots, id, name, start, duration, enable;
	for i=0,4 do
		slots = GetContainerNumSlots(i);
		for j=1,slots do
			start, duration, enable = GetContainerItemCooldown(i,j);
			if enable == 1 and duration > self.db.char.mintime and duration <= self.db.char.maxtime then
				name = select(3, GetContainerItemLink(i,j):find("Hitem[^|]+|h%[([^[]+)%]"))
				if self.db.char.itemgroups[name] then
					name = self.db.char.itemgroups[name];
				end
				if not self.db.char.itemcooldowns[name] then
					self.db.char.itemcooldowns[name] = {
						["disabled"] = false,
						["icon"] = GetContainerItemInfo(i,j),
					};
					if not self.db.char.groups.ItemCooldowns.disabled then
						self.db.char.itemcooldowns[name].group = "ItemCooldowns";
					else
						self.db.char.itemcooldowns[name].group = "CDT";
					end
				end
				if not self.db.char.itemcooldowns[name].disabled and self.db.char.itemcooldowns[name].start ~= start then
					self.db.char.itemcooldowns[name].start = start;
					self:SetUpBar(name, self.db.char.itemcooldowns[name], duration);
				end
			end
		end
	end
	for i=1,18 do
		start, duration, enable = GetInventoryItemCooldown("player", i);
		if enable == 1 and duration > self.db.char.mintime and duration <= self.db.char.maxtime then
			name = select(3, GetInventoryItemLink("player",i):find("Hitem[^|]+|h%[([^[]+)%]"))
			if self.db.char.itemgroups[name] then
				name = self.db.char.itemgroups[name];
			end
			if not self.db.char.itemcooldowns[name] then
				self.db.char.itemcooldowns[name] = {
					["disabled"] = false,
					["icon"] = GetInventoryItemTexture("player", i),
				};
				if not self.db.char.groups.ItemCooldowns.disabled then
					self.db.char.itemcooldowns[name].group = "ItemCooldowns";
				else
					self.db.char.itemcooldowns[name].group = "CDT";
				end
			end
			if not self.db.char.itemcooldowns[name].disabled and self.db.char.itemcooldowns[name].start ~= start then
				self.db.char.itemcooldowns[name].start = start;
				self:SetUpBar(name, self.db.char.itemcooldowns[name], duration);
			end
		end
	end
end

function CooldownTimers:PopulateCooldowns()
	local i = 1;
	local cooldown = GetSpellName(i, BOOKTYPE_SPELL);
	local last;
	while cooldown do
		if cooldown ~= last then
			last = cooldown;
			CDTTooltipTextRight2:SetText("");
			CDTTooltipTextRight3:SetText("");
			tooltip:SetSpell(i, BOOKTYPE_SPELL);
			if (CDTTooltipTextRight2:GetText() and CDTTooltipTextRight2:GetText():find(L["cooldown"]))
				or (CDTTooltipTextRight3:GetText() and CDTTooltipTextRight3:GetText():find(L["cooldown"])) then
				if not self.db.char.cooldowns[cooldown] and not self.db.char.skillgroups[cooldown] then
					self.db.char.cooldowns[cooldown] = {
						["start"] = 0,
						["id"] = i,
						["icon"] = GetSpellTexture(i, BOOKTYPE_SPELL),
						["group"] = "CDT",
					};
				elseif self.db.char.skillgroups[cooldown] and not self.db.char.cooldowns[self.db.char.skillgroups[cooldown] ] then
					self.db.char.cooldowns[self.db.char.skillgroups[cooldown] ] = {
						["start"] = 0,
						["id"] = i,
						["icon"] = GetSpellTexture(i, BOOKTYPE_SPELL),
						["group"] = "CDT",
					};
				elseif self.db.char.cooldowns[cooldown] then
					self.db.char.cooldowns[cooldown].id = i;
				elseif self.db.char.skillgroups[cooldown] and self.db.char.cooldowns[self.db.char.skillgroups[cooldown] ] then
					self.db.char.cooldowns[self.db.char.skillgroups[cooldown] ].id = i;
				end
				if cooldown == L["Preparation"] or cooldown == L["Readiness"] or cooldown == L["Cold Snap"] then
					self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED");
					self.reset = cooldown;
				end
			end
		end
		i = i + 1;
		cooldown = GetSpellName(i, BOOKTYPE_SPELL);
	end
	if UnitExists("pet") then
		self:PopulatePetCooldowns();
	end
	self:SPELL_UPDATE_COOLDOWN();
	self:BAG_UPDATE_COOLDOWN();
end

function CooldownTimers:UNIT_PET()
	if arg1 ~= "player" then return; end
	self:PopulatePetCooldowns();
end

function CooldownTimers:PopulatePetCooldowns()
	if not self:IsEventRegistered("PET_BAR_UPDATE_COOLDOWN") then
		self:RegisterEvent("PET_BAR_UPDATE_COOLDOWN");
	end
	local i = 1;
	local cooldown = GetSpellName(i, BOOKTYPE_PET);
	local last;
	if self.db.char.groups.PetCooldowns == nil then
		self.db.char.groups.PetCooldowns = {};
		self:MakeAnchor("PetCooldowns", self.db.char.groups.PetCooldowns);
	end
	while cooldown do
		if cooldown ~= last then
			--self:Print(cooldown);
			last = cooldown;
			CDTTooltipTextRight2:SetText("");
			CDTTooltipTextRight3:SetText("");
			tooltip:SetSpell(i, BOOKTYPE_PET);
			if (CDTTooltipTextRight2:GetText() and CDTTooltipTextRight2:GetText():find(L["cooldown"]))
				or (CDTTooltipTextRight3:GetText() and CDTTooltipTextRight3:GetText():find(L["cooldown"])) then
				if not self.db.char.petcooldowns[cooldown] then
					self.db.char.petcooldowns[cooldown] = {
						["start"] = 0,
						["id"] = i,
						["icon"] = GetSpellTexture(i, BOOKTYPE_PET),
					};
					if not self.db.char.groups.PetCooldowns.disabled then
						self.db.char.petcooldowns[cooldown].group = "PetCooldowns";
					else
						self.db.char.petcooldowns[cooldown].group = "CDT";
					end
				elseif self.db.char.petcooldowns[cooldown] then
					self.db.char.petcooldowns[cooldown].id = i;
				end
			end
		end
		i = i + 1;
		cooldown = GetSpellName(i, BOOKTYPE_PET);
	end
	self:PET_BAR_UPDATE_COOLDOWN();
end

function CooldownTimers:PET_BAR_UPDATE_COOLDOWN()
	local start, duration, enable, name;
	for k, v in pairs(self.db.char.petcooldowns) do
		name = GetSpellName(v.id, BOOKTYPE_PET);
		if not v.disabled and k == name then
			start, duration, enable = GetSpellCooldown(v.id, BOOKTYPE_PET);
			if enable == 1 and duration > self.db.char.mintime and duration <= self.db.char.maxtime and v.start ~= start then
				v.start = start;
				self:SetUpBar(k, v, duration);
			end
		end
	end
end

function CooldownTimers:UNIT_SPELLCAST_SUCCEEDED()
	if arg1 ~= "player" then return; end
	if arg2 == self.reset then
		self:ResetCooldowns();
	end
end

function CooldownTimers:SetUpBar(skillName, skilloptions, duration)
	--self:Print(skillName);
	local db = self.db.char
	local group = db.groups[skilloptions.group];
	local colors = skilloptions.colors or group.colors or db.barOptions.colors;
	if bars[skillName] then
		self:StopCandyBar(bars[skillName]);
	end
	if group.collapse or (group.collapse == nil and db.barOptions.collapse) then
		local name = "cdt-"..skillName
		if not self:IsCandyBarRegistered(name) then
			self:RegisterCandyBar(name, duration, skilloptions.name or skillName, skilloptions.icon, unpack(colors));
		end
		self:RegisterCandyBarWithGroup(name, skilloptions.group);
		self:SetCandyBarTexture(name, surface:Fetch(skilloptions.texture or group.texture or db.barOptions.texture));
		self:SetCandyBarWidth(name, group.barwidth or db.barOptions.barwidth);
		self:SetCandyBarHeight(name, group.barheight or db.barOptions.barheight);
		self:SetCandyBarScale(name, group.scale or db.barOptions.scale);
		self:SetCandyBarFade(name, skilloptions.fade or group.fade or db.barOptions.scale);
		self:StartCandyBar(name);
		self:SetCandyBarTimeLeft(name, duration - (GetTime() - skilloptions.start));
		self:SetCandyBarCompletion(name, self.BarComplete, self, skillName, skilloptions.icon);
		bars[skillName] = name;
	else
		local i = 1;
		while select(1, self:CandyBarStatus("cdt-group-"..skilloptions.group..i)) and select(4, self:CandyBarStatus("cdt-group-"..skilloptions.group..i)) do
			i = i + 1;
		end
		local name = "cdt-group-"..skilloptions.group..i
		if not self:IsCandyBarRegistered(name) then
			self:RegisterCandyBar(name, 0, "-", "-", unpack(colors));
		end
		self:SetCandyBarTexture(name, surface:Fetch(skilloptions.texture or group.texture or db.barOptions.texture));
		self:SetCandyBarPoint(name, self:GetOffSet(i, group, skilloptions.group));
		self:SetCandyBarWidth(name, group.barwidth or db.barOptions.barwidth);
		self:SetCandyBarHeight(name, group.barheight or db.barOptions.barheight);
		self:SetCandyBarScale(name, group.scale or db.barOptions.scale);
		self:SetCandyBarTime(name, duration);
		self:SetCandyBarIcon(name, skilloptions.icon);
		self:SetCandyBarText(name, skilloptions.name or skillName);
		self:SetCandyBarFade(name, skilloptions.fade or group.fade or db.barOptions.fade);
		self:StartCandyBar(name);
		self:SetCandyBarTimeLeft(name, duration - (GetTime() - skilloptions.start));
		self:SetCandyBarCompletion(name, self.BarComplete, self, skillName, skilloptions.icon);
		bars[skillName] = name;
	end
end

function CooldownTimers:GetOffSet(bar, group, groupName)
	local column = (math.fmod(bar-1, group.columns or self.db.char.barOptions.columns)) * ((group.barheight or self.db.char.barOptions.barheight)+ (group.barwidth or self.db.char.barOptions.barwidth) + (group.bargap or self.db.char.barOptions.bargap));
	local height = (math.floor((bar-1)/(group.columns or self.db.char.barOptions.columns))) * ((group.barheight or self.db.char.barOptions.barheight) + (group.bargap or self.db.char.barOptions.bargap));
	local point = "BOTTOM";
	if (group.up == nil and not self.db.char.barOptions.up) or (group.up == false) then
		height = -height;
		point = "TOP";
	end
	--self:Print(point, anchors[groupName]:GetName(), "BOTTOM", column, height);
	return point, anchors[groupName]:GetName(), "BOTTOM", column, height;	
end

function CooldownTimers:KillAllBars()
	for k,v in pairs(bars) do
		self:StopCandyBar(v);
		bars[k] = nil;
	end
end

function CooldownTimers:FixGroups()
	for k,v in pairs(self.db.char.cooldowns) do
		if not v.group or not self.db.char.groups[v.group] or self.db.char.groups[v.group].disabled then
			self:Print(k,L["moved from group"],v.group,L["to"],"CDT");
			v.group = "CDT";
		end
	end
	for k,v in pairs(self.db.char.petcooldowns) do
		if not v.group or not self.db.char.groups[v.group] or self.db.char.groups[v.group].disabled then
			self:Print(k,L["moved from group"],v.group,L["to"],"CDT");
			v.group = "CDT";
		end
	end
	for k,v in pairs(self.db.char.itemcooldowns) do
		if not v.group or not self.db.char.groups[v.group] or self.db.char.groups[v.group].disabled then
			self:Print(k,L["moved from group"],v.group,L["to"],"CDT");
			v.group = "CDT";
		end
	end
end

function CooldownTimers:BarComplete(skill, icon)
	bars[skill] = nil;
	if not self.db.char.announce.enabled then return; end
	self.announce.text:SetText(self.db.char.announce.announceString:format(skill));
	self.announce.last = GetTime();
	self.announce.alpha = 1;
	self.announce.frame:Show();
	PlaySound("Deathbind Sound");
end

