-- Copyright (c) 2008 kydori <kydori@gmail.com>

local adb = LibStub("AceDB-3.0")
local acd = LibStub("AceConfigDialog-3.0")
local ac = LibStub("AceConfig-3.0")
local L = LibStub("AceLocale-3.0"):GetLocale(Aesa.appName)
local sm = LibStub("LibSharedMedia-3.0")

local lang = {target = L["Target"], focus = L["Focus"]}
local textures = {"Button", "Frost", "LiteStepLite", "LiteStepLite2", "Steel", "Ruben", "Ruben2"}
for _, v in pairs(textures) do
	sm:Register("statusbar", v, "Interface\\Addons\\" .. Aesa.appName .. "\\Data\\Textures\\" .. v)
end

Aesa.defaults = {
	profile = {
		version = Aesa.version,
		enabled = true,
		locked = true,
		cd = {
			["**"] = {
				enabled = true,
				tabbed = true,
				tabs = 4,
				tabHeight = 20,
				tabSpacing = 4,
				tabTexture = "Ruben2",
				tabFont = "Friz Quadrata TT",
				tabFontSize = 9,
				tabAlpha1 = 0.3,
				tabAlpha2 = 1,
				font = "Friz Quadrata TT",
				fontSize = 10,
				texture = "Steel",
				height = 16,
				width = 160,
				spacing = 1,
				iconSide = "LEFT",
				growUp = true,
				rows = 12,
				backgroundColor = {0, 0, 0, 1},
				barColor = {0.42, 0.69, 1, 1},
				highlightColor = {0, 0.98, 0.36, 1},
				textColor = {1, 1, 1},
				alpha = 1,
				scale = 1,
				hostileOnly = false,
				timeLimit = 360,
				highlightNew = true,
				highlightColor = {1, 0.8, 0, 1}
			},
			target = {},
			focus = {
				enabled = false
			}
		}
	}
}

function Aesa:Reset()
	self.cds = {}
	self.trackers = {
		target = {unitGUID = -1, timers = {}},
		focus = {unitGUID = -1, timers = {}}
	}
	self.nameplates = {
		target = {tabID = -1, units = {}, tabs = {}},
		focus = {tabID = -1, units = {}, tabs = {}}
	}
end

function Aesa:OnInitialize()
	self.db = adb:New(self.dbName, self.defaults)
	self.db.RegisterCallback(self, "OnProfileChanged", function() self:C_ApplySettings() end)
	self.db.RegisterCallback(self, "OnProfileCopied", function() self:C_ApplySettings() end)
	self.db.RegisterCallback(self, "OnProfileReset", function() self:C_ApplySettings() end)
  ac:RegisterOptionsTable(self.appName, self:GetOptions())
	acd:AddToBlizOptions(self.appName)
  self:RegisterChatCommand("aesa", "ChatCommand")
	self:Print("|cffffff78 v" .. self.version .. "|r (c) Kydori,Ananhaid " .. L["Type %s for options."]:format("|cff00ff00/aesa|r"));
	self:Print(L["Uncheck [LOCK] checkbox in setup menu to move bars."]);
end

function Aesa:OnEnable()
	local db = self.db.profile
	db.locked = true
	self:Reset()
	self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
	self:RegisterEvent("PLAYER_TARGET_CHANGED")
	self:RegisterEvent("PLAYER_FOCUS_CHANGED")
	self:RegisterEvent("PLAYER_ENTERING_WORLD")
	self:C_ApplySettings(true)
end

function Aesa:OnDisable()
	local db = self.db.profile
	db.locked = true
	for k, _ in pairs(self.trackers) do
		self:ClearTracker(k)
		self:ClearTabs(k)
	end
	self:Reset()
end

function Aesa:ChatCommand(input)
	acd:Open(self.appName)
end

function Aesa:OpenConfigDialog()
	local f = acd.OpenFrames[self.appName]
	acd:Open(self.appName)
	if not f then
		f = acd.OpenFrames[self.appName]
		f:SetWidth(400)
		f:SetHeight(600)
	end
end

function Aesa:COMBAT_LOG_EVENT_UNFILTERED(_, timestamp, eventType, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, spellID, spellName, spellSchool, detail1, detail2, detail3)
	local db = self.db.profile
	local isPlayer = (srcGUID == playerGUID) and false
	if not db.enabled or not db.locked or not srcGUID or isPlayer then return end
	local isSrcEnemy = self:IsEnemy(srcFlags)
	if eventType == "SPELL_CAST_SUCCESS" then
		if not spellID then return end
		local cdID = srcGUID .. "." .. spellID
		local ignore = true
		for k, _ in pairs(self.trackers) do
			local dbx = db.cd[k]
			if dbx.enabled and not dbx.locked and (isSrcEnemy or not dbx.hostileOnly) then
				ignore = false
				break
			end
		end
		if ignore then return end
		local spell = self.spells[spellID]
		-- Handle chained cooldowns.
		if not self:IsTable(spell) then return end
		if self:IsTable(spell[4]) then
			for _, sid in pairs(spell[4]) do
				if v == -1 then
					self:RemoveCDsByUnitSpell(srcGUID, -1)
					do break end
				elseif sid > 0 then
					self:RemoveCDsByUnitSpell(srcGUID, sid)
				end
			end
		end
		self:RegisterCD(srcGUID, srcName, srcFlags, spellID)
		for k, v in pairs(self.trackers) do
			local tabID = self.nameplates[k].tabID
			local activeGUID = (not db.cd[k].tabbed or self:ToNumber(tabID) < 0) and v.unitGUID or tabID
			if srcGUID == activeGUID then
				self:UpdateTracker(k)
			end
		end
	elseif eventType == "UNIT_DIED" then
		if (self.cds[srcGUID]) then
			self:RemoveCDsByUnitSpell(srcGUID, -1)
			self:RemoveUnitTab(srcGUID, true)
		end
	end
end

function Aesa:PLAYER_TARGET_CHANGED()
	local db = self.db.profile.cd.target
	local unitGUID = UnitGUID("target")
	local playerGUID = UnitGUID("player")
	if not unitGUID or unitGUID == playerGUID or UnitIsDead("target") or not UnitPlayerControlled("target") then
		return
	end
	local isEnemy = UnitIsEnemy("player", "target")
	for k, _ in pairs(self.nameplates) do
		local dbx = self.db.profile.cd[k]
		if dbx.tabbed then
			local currentTime = GetTime()
			if isEnemy or not dbx.hostileOnly then
				local _, unitClass = UnitClass("target")
				local unitName = UnitName("target")
				self.nameplates[k].units[unitGUID] = {unitGUID = unitGUID, unitName = unitName, unitClass = unitClass, time = currentTime}
				self:UpdateTabs(k)
			end
		end
	end
	if not db.enabled then return end
	if isEnemy or not db.hostileOnly then
		self.trackers.target.unitGUID = unitGUID
		self:UpdateTracker("target")
	end
end

function Aesa:PLAYER_FOCUS_CHANGED()
	local db = self.db.profile.cd.focus
	if not db.enabled then return end
	local focusGUID = UnitGUID("focus")
	if not focusGUID or focusGUID == UnitGUID("player") or UnitIsDead("focus") or not UnitPlayerControlled("target") then
		self:ClearTracker("focus")
		return
	end
	self.trackers.focus.unitGUID = focusGUID
	self:UpdateTracker("focus")
end

function Aesa:PLAYER_ENTERING_WORLD()
	local db = self.db.profile
	db.locked = true
	for k, _ in pairs(self.trackers) do
		Aesa:ClearTabs(k, true)
		Aesa:ClearTracker(k)
		Aesa:ResetPoints(k)
	end
	self:Reset()
end

function Aesa:RegisterCD(srcGUID, srcName, srcFlags, spellID)
	local cd1, cd2 = self.spells[spellID][2], self.spells[spellID][3]
	local cd = (cd2 > 0 and cd2 or cd1)
	local spellName, spellRank, spellIcon = GetSpellInfo(spellID)
	if not self.cds[srcGUID] then self.cds[srcGUID] = {} end
	local currentTime = GetTime()
	self.cds[srcGUID][spellID] = {
		cdID = srcGUID .. "|" .. spellID,
		flags = srcFlags,
		srcName = srcName,
		srcGUID = srcGUID,
		spellID = spellID,
		spellName = spellName,
		spellRank = spellRank,
		spellIcon = spellIcon,
		startTime = currentTime,
		endTime = currentTime + cd,
		duration = cd,
		elapsed = 0,
		remaining = cd
	}
end

function Aesa:RemoveCDsByUnitSpell(unitGUID, spellID)
	if not unitGUID then return end
	local unitCDs = self.cds[unitGUID]
	if not unitCDs then return end
	if spellID then
		unitCDs[spellID] = nil
	elseif spellID == -1 then
		self.cds[unitGUID] = nil
	end
end

function Aesa:CreateTimer()
	local t = CreateFrame("StatusBar", nil, UIParent)
	t:Hide()
	t:SetFrameStrata("MEDIUM")
	t:SetClampedToScreen(true)
	t:SetScript("OnUpdate", function() self:C_OnTimerUpdate() end)
	t:SetBackdrop({bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16})
	t:SetBackdropColor(0, 0, 0, 1)
	t.icon = t:CreateTexture(nil, "DIALOG")
	local ti = t.icon
	ti:SetTexCoord(0.07, 0.93, 0.07, 0.93)
	t.spellText = t:CreateFontString(nil, "OVERLAY")
	local st = t.spellText
	st:SetNonSpaceWrap(false)
	st:SetPoint("LEFT", t, "LEFT", 2, 0)
	st:SetJustifyH("LEFT")
	st:SetShadowColor(0, 0, 0, 1)
	st:SetShadowOffset(0.8, -0.8)
	t.timeText = t:CreateFontString(nil, "OVERLAY")
	local tt = t.timeText
	tt:SetNonSpaceWrap(false)
	tt:SetPoint("RIGHT", t, "RIGHT", -2, 0)
	tt:SetJustifyH("RIGHT")
	tt:SetShadowColor(0, 0, 0, 1)
	tt:SetShadowOffset(0.8, -0.8)
	local s = t:CreateTexture(nil, "OVERLAY")
	t.spark = s
	s:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark")
	s:SetWidth(24)
	s:SetBlendMode("ADD")
	return t
end

function Aesa:UpdateTracker(trackerID)
	if not trackerID then return end
	self:ClearTracker(trackerID)
	local db = self.db.profile.cd[trackerID]
	if not db.enabled then return end
	local timers = self.trackers[trackerID].timers
	local tabID = self.nameplates[trackerID].tabID
	local activeGUID = (self:ToNumber(tabID) < 0 and self.trackers[trackerID].unitGUID or tabID)
	local unitCDs = self.cds[activeGUID]
	if not unitCDs then return end
	local tmp = {}
	local m = 1
	local lastCD = {spellID = -1, time = -1}
	for spellID, cd in pairs(unitCDs) do
		if Aesa:IsTable(cd) then
			local currentTime = GetTime()
			cd.elapsed = currentTime - cd.startTime
			cd.remaining = cd.duration - cd.elapsed
			if (cd.remaining and cd.remaining > 0 and cd.remaining <= db.timeLimit) then
				if (cd.startTime > lastCD.time) then
					lastCD.spellID = spellID
					lastCD.time = cd.startTime
				end
				tmp[m] = {spellID = spellID, remaining = self:ToNumber(cd.remaining)}
				m = m + 1
			end
		end
		if m > db.rows then break end
	end
	table.sort(tmp, function(a, b) if db.growUp then return self:C_RemainingComparer(a, b) else return self:C_ReversalRemainingComparer(a, b) end end)
	if not self:IsTable(timers) or #timers < db.rows then
		self:ResetPoints(trackerID, "T")
	end
	local n = 1
	for k, v in ipairs(tmp) do
		if timers[k] and timers[k].points then
			local cd = unitCDs[v.spellID]
			if cd and cd.cdID then
				if not timers[k].timer then
					timers[k].timer = self:CreateTimer()
				end
				local t = timers[k].timer
				t.trackerID = trackerID
				t.cdID = cd.cdID
				t.unitGUID = cd.srcGUID
				t.spellID = cd.spellID
				t:ClearAllPoints()
				t:SetScale(db.scale)
				t:SetMinMaxValues(cd.startTime, cd.endTime)
				t:SetStatusBarTexture(sm:Fetch("statusbar", db.texture))
				if v.spellID == lastCD.spellID and db.highlightNew then
					t:SetStatusBarColor(unpack(db.highlightColor))
				else
					t:SetStatusBarColor(unpack(db.barColor))
				end
				t:SetWidth(db.width)
				t:SetHeight(db.height)
				t:SetAlpha(db.alpha)
				t:SetPoint(unpack(timers[k].points))
				-- spellText
				local st = t.spellText
				st:SetWidth(db.width * 7 / 10)
				st:SetFont(sm:Fetch("font", db.font), db.fontSize)
				self:FontStringSetText(st, cd.spellName)
				local tt = t.timeText
				tt:SetWidth(db.width / 5)
				tt:SetFont(sm:Fetch("font", db.font), db.fontSize)
				tt:SetText(self:Time(cd.duration))
				-- icon
				local ti = t.icon
				ti:ClearAllPoints()
				ti:SetTexture(cd.spellIcon)
				ti:SetWidth(db.height)
				ti:SetHeight(db.height)
				if db.iconSide == "LEFT" then
					ti:SetPoint("RIGHT", t, "LEFT", 0, 0)
				else
					ti:SetPoint("LEFT", t, "RIGHT", 0, 0)
				end
				local s = t.spark
				s:SetHeight(db.height + 22)
				t:Show()
				ti:Show()
				st:Show()
				tt:Show()
				s:Show()
			end
		end
	end
end

function Aesa:ClearTracker(trackerID)
	local timers = self.trackers[trackerID].timers
	for k, v in ipairs(timers) do
		if self:IsTable(v) and v.timer and v.timer.trackerID then
			v.timer:Hide()
			timers[k].timer = nil
		end
	end
end

function Aesa:CreateTab()
	local t = CreateFrame("CheckButton", nil, UIParent)
	t:Hide()
	t:EnableMouse(true)
	t:RegisterForClicks("LeftButtonUp", "RightButtonUp")
	t:SetScript("OnClick", function(...) self:C_OnTabClick(...) end)
	t:SetScript("OnEnter", function(...) self:C_OnTabEnter(...) end)
	t:SetScript("OnLeave", function(...) self:C_OnTabLeave(...) end)
	t:SetFrameStrata("MEDIUM")
	t:SetClampedToScreen(true)
	t:SetBackdrop({bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16})
	t:SetBackdropColor(0, 0, 0, 1)
	t.button = t:CreateTexture(nil, "OVERLAY")
	local b = t.button
	b:SetAllPoints(t)
	t:SetNormalTexture(b)
	t:SetHighlightTexture("Interface\\CastingBar\\UI-CastingBar-Spark")
	t:SetCheckedTexture("Interface\\Buttons\\UI-DialogBox-Button-Highlight")
	t.nameText = t:CreateFontString(nil, "OVERLAY")
	local nt = t.nameText
	nt:SetNonSpaceWrap(false)
	nt:SetPoint("CENTER", t, "CENTER", 0, 0)
	nt:SetJustifyH("CENTER")
	nt:SetShadowColor(0, 0, 0, 1)
	nt:SetShadowOffset(0.8, -0.8)
	return t
end

function Aesa:UpdateTabs(trackerID)
	if not trackerID then return end
	self:ClearTabs(trackerID)
	local db = self.db.profile.cd[trackerID]
	if not db.enabled or not db.tabbed then return end
	local np = self.nameplates[trackerID]
	local units = np.units
	local tabs = np.tabs
	local tmp, tmp2 = {}, {}
	local m = 1
	for unitID, info in pairs(units) do
		if self:IsTable(info) and info.time and info.time > 0 then
			if info.unitGUID == np.tabID and np.tabID ~= -1 then
				info.time = GetTime() + 1
				tmp[m] = info
			else
				tmp[m] = info
			end
			tmp2[info.unitGUID] = info
			m = m + 1
		end
	end
	tmp[#tmp + 1] = {unitGUID = -1, unitName = lang[trackerID], unitClass = nil, time = GetTime() + 7200}
	table.sort(tmp, function(a, b) return a.time > b.time end)
	if not self:IsTable(tabs) or #tabs < db.tabs then
		self:ResetPoints(trackerID, "N")
	end
	local n = 1
	for k, v in ipairs(tmp) do
		if v.unitGUID ~= -1 then
			tmp2[v.unitGUID] = v
		end
		if k > db.tabs + 5 then break end
		local tab = tabs[k]
		if tab and tab.points and n <= db.tabs then
			n = n + 1
			tab.tab = self:CreateTab()
			local t = tab.tab
			t.trackerID = trackerID
			t.unitGUID = v.unitGUID
			t.unitName = v.unitName
			t.unitClass = v.unitClass
			t:ClearAllPoints()
			t:SetScale(db.scale)
			t:SetWidth(tab.width)
			t:SetHeight(db.tabHeight)
			t:SetAlpha(db.tabAlpha1)
			t:SetPoint(unpack(tab.points))
			local b = t.button
			b:SetTexture(sm:Fetch("statusbar", db.tabTexture))
			b:SetVertexColor(self:GetClassColor(t.unitClass))
			local nt = t.nameText
			nt:SetWidth(t:GetWidth())
			nt:SetFont(sm:Fetch("font", db.tabFont), db.tabFontSize)
			self:FontStringSetText(nt, t.unitName)
			if (t.unitGUID == np.tabID) then
				t:SetChecked(true)
			end
			t:Show()
			nt:Show()
		end
	end
	np.units = tmp2
end

function Aesa:RemoveUnitTab(unitGUID, update)
	for k, _ in self.trackers do
		if (self.nameplates[k].units[unitGUID]) then
			self.nameplates[k].units[unitGUID] = nil
			if (update) then self:UpdateTabs(k) end
		end
	end
end

function Aesa:ClearTabs(trackerID, resetTabID)
	local tabs = self.nameplates[trackerID].tabs
	for k, v in ipairs(tabs) do
		if self:IsTable(v) and v.tab and v.tab.trackerID then
			v.tab:Hide()
			tabs[k].tab = nil
		end
	end
	if (resetTabID) then
		self.nameplates[trackerID].tabID = -1
	end
end

function Aesa:CreateAnchor(trackerID)
	local t = self:CreateTimer()
	local db = self.db.profile.cd[trackerID]
	local currentTime = GetTime()
	t.cdID = "-1.-1"
	t.trackerID = trackerID
	t.startTime = currentTime
	t.endTime = currentTime + 600
	t:EnableMouse(true)
	t:SetMovable(true)
	t:RegisterForDrag("LeftButton")
	t:SetScript("OnDragStart", function() self:C_OnDragStart() end)
	t:SetScript("OnDragStop", function() self:C_OnDragStop() end)
	t:SetScript("OnUpdate", nil)
	return t
end

function Aesa:ShowAnchors(hide)
	for trackerID, _ in pairs(self.trackers) do
		self:ClearTracker(trackerID)
		if not hide then
			local db = self.db.profile.cd[trackerID]
			self:ResetPoints(trackerID, "T")
			local tx = self.trackers[trackerID].timers[1]
			tx.timer = self:CreateAnchor(trackerID)
			local t = tx.timer
			-- spellText
			t:ClearAllPoints()
			local st = t.spellText
			st:SetWidth(db.width)
			st:SetFont(sm:Fetch("font", db.font), db.fontSize)
			self:FontStringSetText(st, lang[trackerID] .. ": " .. L["Drag to move"])
			-- icon
			local ti = t.icon
			ti:ClearAllPoints()
			ti:SetTexture("Interface\\Icons\\Spell_Nature_HealingTouch")
			ti:SetWidth(db.height)
			ti:SetHeight(db.height)
			if db.iconSide == "LEFT" then
				ti:SetPoint("RIGHT", t, "LEFT", 0, 0)
			else
				ti:SetPoint("LEFT", t, "RIGHT", 0, 0)
			end
			local s = t.spark
			s:SetHeight(db.height + 25)
			t:SetMinMaxValues(t.startTime, t.endTime)
			t:SetStatusBarTexture(sm:Fetch("statusbar", db.texture))
			t:SetStatusBarColor(1, 0, 0, 1)
			t:SetScale(db.scale)
			t:SetWidth(db.width)
			t:SetHeight(db.height)
			t:SetAlpha(db.alpha)
			t:SetPoint(unpack(tx.points))
			t:Show()
			ti:Show()
			st:Show()
			s:Show()
		end
	end
end

function Aesa:GetClassColor(class)
  class = string.upper(self:ToString(class))
  if RAID_CLASS_COLORS and RAID_CLASS_COLORS[class] then
    return RAID_CLASS_COLORS[class].r, RAID_CLASS_COLORS[class].g, RAID_CLASS_COLORS[class].b
  else
    return 0.5, 0.5, 0.5
  end
end

function Aesa:Time(time)
	return (time <= 10 and string.format("%.1fs", time))
		or (time <= 60 and string.format("%ds", time))
		or (string.format("%.1fm", time / 60))
end

function Aesa:ResetPoints(trackerID, flags)
  local db = self.db.profile.cd[trackerID]
  local x, y, w, h = db.x, db.y, db.width, db.height
  local r, sp = db.rows, db.spacing
	local th, tsp, q = db.tabHeight, db.tabSpacing, db.tabs
	local tw = (w - (q - 1) * tsp) / q
	local f = (db.growUp and 1 or -1)
	if not x or not y then
		x = GetScreenWidth() / 2
		y = GetScreenHeight() / 2
	end
	if not flags or flags == "T" then
		self.trackers[trackerID].timers = {}
		local timers = self.trackers[trackerID].timers
		for i = 1, r do
			timers[i] = {points = {"BOTTOMLEFT", UIParent, "BOTTOMLEFT", x, y + (h + sp) * (i - 1) * f}}
		end
	end
	if not flags or flags == "N" then
		self.nameplates[trackerID].tabs = {}
		local tabs = self.nameplates[trackerID].tabs
		local dy = f > 0 and th or h
		for i = 1, q do
			tabs[i] = {width = tw, points = {"BOTTOMLEFT", UIParent, "BOTTOMLEFT", x + (tw + tsp) * (i - 1), y - (dy + tsp + 5) * f}}
		end
	end
end

function Aesa:FontStringSetText(fontString, text)
	if not fontString or not text then return end
	fontString:SetText(text)
	local w = fontString:GetWidth()
	local sw = fontString:GetStringWidth()
	if w < 1 then return end
	while sw > w and string.len(text) > 1 do
		local j = math.ceil(string.len(text) * 3 / 4) - 1
		text = j > 1 and string.sub(text, 1, j) or ""
		fontString:SetText(text)
		w = fontString:GetWidth()
		sw = fontString:GetStringWidth()
	end
end

function Aesa:SMList()
	local list = sm:List("statusbar")
	local bt = {}
	for k, v in pairs(list) do
		bt[v] = v
	end
	return bt
end

function Aesa:IsEnemy(flags)
	return (bit.band(flags, COMBATLOG_OBJECT_REACTION_HOSTILE) == COMBATLOG_OBJECT_REACTION_HOSTILE)
end

function Aesa:C_RemainingComparer(a, b)
	return b.remaining < a.remaining
end

function Aesa:C_ReversalRemainingComparer(b, a)
	return b.remaining < a.remaining
end

function Aesa:C_OnTimerUpdate()
	local u = Aesa.cds[this.unitGUID]
	if not u or not u[this.spellID] then
		Aesa:UpdateTracker(this.trackerID)
		return
	end
	local cd = u[this.spellID]
	local currentTime = GetTime()
	if currentTime > cd.endTime then
		Aesa:UpdateTracker(this.trackerID)
		return
	end
	this.timeText:SetText(Aesa:Time(cd.endTime - currentTime))
	cd.elapsed = currentTime - cd.startTime
	cd.remaining = cd.duration - cd.elapsed
	local x = this:GetWidth() * cd.elapsed / (cd.endTime - cd.startTime)
	this.spark:SetPoint("CENTER", this, "RIGHT", -x, 0)
	this:SetValue(cd.endTime - cd.elapsed)
end

function Aesa:C_ApplySettings(clearUI)
	local db = Aesa.db.profile
	for k, _ in pairs(self.trackers) do
		Aesa:ClearTabs(k, true)
		Aesa:ClearTracker(k)
		Aesa:ResetPoints(k)
	end
	Aesa:ShowAnchors(db.locked)
	if db.locked and not clearUI then
		for k, _ in pairs(self.trackers) do
			Aesa:UpdateTracker(k)
			Aesa:UpdateTabs(k)
		end
	end
end

function Aesa:C_OnDragStart()
	this:StartMoving()
end

function Aesa:C_OnDragStop()
  local db = Aesa.db.profile.cd[this.trackerID]
	db.x = this:GetLeft()
  db.y = this:GetBottom()
	this:StopMovingOrSizing()
end

function Aesa:C_OnTabClick(frame, button)
	local trackerID = this.trackerID
	local unitGUID = this.unitGUID
	local np = Aesa.nameplates[trackerID]
	if this:GetChecked() then
		np.tabID = unitGUID
		for k, v in pairs(np.tabs) do
			if v and v.tab and v.tab.unitGUID ~= unitGUID then
				v.tab:SetChecked(false)
			end
		end
	else
		np.tabID = -1
		for k, v in pairs(np.tabs) do
			if v and v.tab then
				v.tab:SetChecked(v.tab.unitGUID == -1)
			end
		end
	end
	Aesa:UpdateTracker(trackerID)
end

function Aesa:C_OnTabEnter()
	local trackerID = this.trackerID
	local db = Aesa.db.profile.cd[trackerID]
	local np = Aesa.nameplates[trackerID]
	for k, v in pairs(np.tabs) do
		if v.tab then v.tab:SetAlpha(db.tabAlpha2) end
	end
end

function Aesa:C_OnTabLeave()
	local trackerID = this.trackerID
	local db = Aesa.db.profile.cd[trackerID]
	local np = Aesa.nameplates[trackerID]
	for k, v in pairs(np.tabs) do
		if v.tab then v.tab:SetAlpha(db.tabAlpha1) end
	end
end
