local T, C, L, _ = unpack(select(2, ...))
------------------------------------
-- Nameplate by paopao001@AltzUI
------------------------------------

local cfg = C.Module.Unitframe.Nameplate
local bar_border = C.Media.path .. C.Media.style .. "\\" .. "tex_bar_border"

-- Class Nameplate
local function RedrawManaBar()
	local manaBar = ClassNameplateManaBarFrame
	manaBar:SetWidth(cfg.castbarWidth)
	manaBar:SetHeight(cfg.castbarHeight)
	manaBar:SetStatusBarTexture(C.Media.Texture.status)
	manaBar.SetWidth = T.Dummy
	manaBar.SetHeight = T.Dummy
	manaBar.FullPowerFrame:ClearAllPoints()
	manaBar.FeedbackFrame.BarTexture:SetTexture(C.Media.Texture.status)
end

local function MoveClassResource(onTarget, bar)
	if (not bar) then
		return
	end
	local showSelf = GetCVar("nameplateShowSelf")
	if (showSelf == "0") then
		return
	end

	if (onTarget and NamePlateTargetResourceFrame) then
		local namePlateTarget = C_NamePlate.GetNamePlateForUnit("target")
		if (namePlateTarget) then
			NamePlateTargetResourceFrame:ClearAllPoints()
			NamePlateTargetResourceFrame:SetPoint("CENTER", namePlateTarget.UnitFrame.castBar, "TOP", 0, 2)
		end
	elseif (not onTarget and NamePlatePlayerResourceFrame) then
		local namePlatePlayer = C_NamePlate.GetNamePlateForUnit("player")
		if (namePlatePlayer) then
			NamePlatePlayerResourceFrame:ClearAllPoints()
			NamePlatePlayerResourceFrame:SetPoint("BOTTOM", namePlatePlayer.UnitFrame, "TOP", 0, 0)
		end
	end
end

-- Auras
local function FormatTime(seconds)
	local d, h, m, str = 86400, 3600, 60
	if seconds >= d then
		str = format("%d"..T.colorstring.."d", seconds/d)
	elseif seconds >= h then
		str = format("%d"..T.colorstring.."h", seconds/h)
	elseif seconds >= m then
		str = format("%d"..T.colorstring.."m", seconds/m)
	else
		if seconds <= 5 then
			str = format("|cffff0000%.1f|r", seconds) -- red
		elseif seconds <= 10 then
			str = format("|cffffff00%.1f|r", seconds) -- yellow
		else
			str = format("%d", seconds)
		end
	end
	return str
end

local function CreateAuraIcon(parent)
	local button = CreateFrame("Frame", nil, parent)
	button:SetSize(cfg.auraSize, cfg.auraSize)

	button:SetTextureBorder()

    button.icon = button:CreateTexture(nil, "ARTWORK")
    button.icon:ClearAllPoints()
    button.icon:SetPoint("TOPLEFT", button, cfg.icon_padding, -cfg.icon_padding)
    button.icon:SetPoint("BOTTOMRIGHT", button, -cfg.icon_padding, cfg.icon_padding)
    button.icon:SetTexCoord(unpack(C.Media.texCoord))
    button.icon:SetDrawLayer("BACKGROUND",-8)

    button.text = button:CreateFontString(nil, "OVERLAY")
    button.text:SetPoint("TOPRIGHT", button, "TOPRIGHT", 2, 6)
    button.text:SetJustifyH("CENTER")
    button.text:SetFont(unpack(C.Media.standard_font))

    button.count = button:CreateFontString(nil,"OVERLAY")
    button.count:SetFont(unpack(C.Media.standard_font))
    button.count:SetShadowColor(0, 0, 0, 0.4)
    button.count:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", 2, -6)

    button.overlay = button:CreateTexture(nil, "ARTWORK", nil, 7)
	button.overlay:SetTexture(C.Media.Texture.border)
	button.overlay:SetAllPoints(button)
	button.overlay:SetTexCoord(0, 1, 0, 1)
    button.overlay:SetDrawLayer("BACKGROUND", -7)

    button:CreateShadow()

    return button
end

local function UpdateAuraIcon(button, unit, index, filter)
	local name, _, icon, count, debuffType, duration, expirationTime, _, _, _, spellID = UnitAura(unit, index, filter)

	button.icon:SetTexture(icon)
	button.expirationTime = expirationTime
	button.duration = duration
	button.spellID = spellID

	local color = DebuffTypeColor[debuffType] or DebuffTypeColor.none
	if cfg.colorBorder then
		button.overlay:SetVertexColor(color.r, color.g, color.b)
	else
		button.overlay:SetVertexColor(0, 0, 0)
	end

	if count and count > 1 then
		button.count:SetText(count)
	else
		button.count:SetText("")
	end

	button:SetScript("OnUpdate", function(self, elapsed)
		if not self.duration then return end
		self.elapsed = (self.elapsed or 0) + elapsed
		self.elapsed = 0
		local timeLeft = self.expirationTime - GetTime()
		if timeLeft <= 0 then
			self.text:SetText(nil)
		else
			self.text:SetText(FormatTime(timeLeft))
		end
	end)
	button:Show()
end

local function AuraFilter(caster, spellid)
	if caster == "player" then	--1:none,2:all,3:white,4:black
		if cfg.myFilterMode == 1 then
			return false
		elseif cfg.myFilterMode == 2 then
			return true
		elseif cfg.myFilterMode == 3 and C.Aura.Nameplate.WhiteList[spellid] then
			return true
		elseif cfg.myFilterMode == 4 and not C.Aura.Nameplate.BlackList[spellid] then
			return true
		end
	else	--1:none,2:black
		if cfg.otherFilterMode == 1 then
			return false
		elseif cfg.otherFilterMode == 2 and C.Aura.Nameplate.OtherList[spellid] then
			return true
		end
	end
end

local function UpdateBuffs(unitFrame)
	if not unitFrame.icons or not unitFrame.displayedUnit then return end
	local unit = unitFrame.displayedUnit
	local i = 1

	for index = 1, 15 do
		if i <= cfg.maxAuras then
			local bname, _, _, _, _, bduration, _, bcaster, _, _, bspellid = UnitAura(unit, index, "HELPFUL")
			local matchbuff = AuraFilter(bcaster, bspellid)
			if bname and matchbuff then
				if not unitFrame.icons[i] then
					unitFrame.icons[i] = CreateAuraIcon(unitFrame)
				end
				UpdateAuraIcon(unitFrame.icons[i], unit, index, "HELPFUL")
				if i ~= 1 then
					if i == 6 then
						unitFrame.icons[6]:SetPoint("BOTTOM", unitFrame.icons[1], "TOP", 0, 4)
					else
						unitFrame.icons[i]:SetPoint("LEFT", unitFrame.icons[i-1], "RIGHT", 4, 0)
					end
				end
				i = i + 1
			end
		end
	end

	for index = 1, 20 do
		if i <= cfg.maxAuras then
			local dname, _, _, _, _, dduration, _, dcaster, _, _, dspellid = UnitAura(unit, index, "HARMFUL")
			local matchdebuff = AuraFilter(dcaster, dspellid)
			if dname and matchdebuff then
				if not unitFrame.icons[i] then
					unitFrame.icons[i] = CreateAuraIcon(unitFrame)
				end
				UpdateAuraIcon(unitFrame.icons[i], unit, index, "HARMFUL")
				if i ~= 1 then
					if i == 6 then
						unitFrame.icons[6]:SetPoint("BOTTOM", unitFrame.icons[1], "TOP", 0, 4)
					else
						unitFrame.icons[i]:SetPoint("LEFT", unitFrame.icons[i-1], "RIGHT", 4, 0)
					end
				end
				i = i + 1
			end
		end
	end
	unitFrame.iconnumber = i - 1

	if i > 1 then
		local count = i > 5 and 5 or unitFrame.iconnumber
		unitFrame.icons[1]:SetPoint("LEFT", unitFrame.icons, "CENTER", -((cfg.auraSize + 4)*count - 4)/2, 0)
	end
	for index = i, #unitFrame.icons do unitFrame.icons[index]:Hide() end
end

-- Unitframe
local function UpdateName(unitFrame)
	local name = GetUnitName(unitFrame.displayedUnit, false)
	local level = UnitLevel(unitFrame.displayedUnit)
	if level and level ~= UnitLevel("player") then
		if level == -1 then
			level = "|cffff0000Boss|r "
		else 
			level = T.RGBToHex(GetQuestDifficultyColor(level))..level.."|r "
		end
	else
		level = ""
	end
	if name then
		if UnitIsUnit(unitFrame.displayedUnit, "player") then
			unitFrame.name:SetText("")
		else
			unitFrame.name:SetText(level..name)
		end
	end
end

local function UpdateHealth(unitFrame)
	local unit = unitFrame.displayedUnit
	local minHealth, maxHealth = UnitHealth(unit), UnitHealthMax(unit)
	local p = minHealth/maxHealth * 100

	unitFrame.healthBar:SetValue(p/100)
	if minHealth ~= maxHealth then 
		unitFrame.healthBar.value:SetText(string.format("%d%%", p))
	else
		unitFrame.healthBar.value:SetText("")
	end
	if (p <= 50 and p >= 35) then
		unitFrame.healthBar.value:SetTextColor(253/255, 238/255, 80/255)
	elseif (p < 35 and p >= 20) then
		unitFrame.healthBar.value:SetTextColor(250/255, 130/255, 0/255)
	elseif (p < 20) then
		unitFrame.healthBar.value:SetTextColor(200/255, 20/255, 40/255)
	else
		unitFrame.healthBar.value:SetTextColor(1, 1, 1)
	end
	T.SmoothBar(unitFrame.healthBar)
end

local function IsTapDenied(unitFrame)
	return UnitIsTapDenied(unitFrame.unit) and not UnitPlayerControlled(unitFrame.unit)
end

local function UpdateHealthColor(unitFrame)
	local hp = unitFrame.healthBar
	local unit = unitFrame.displayedUnit
	local _, status = UnitDetailedThreatSituation("player", unitFrame.displayedUnit)
	local r, g, b

	if ( not UnitIsConnected(unit) ) then
		r, g, b = .7, .7, .7
	else
		local _, Class = UnitClass(unit)
		local classColor = (CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS)[Class]
		if UnitIsPlayer(unit) and classColor and cfg.friendlyCC and UnitReaction(unit, "player") >= 5 then
			r, g, b = classColor.r, classColor.g, classColor.b
		elseif UnitIsPlayer(unit) and classColor and cfg.nemyCC and UnitReaction(unit, "player") <= 4 then
			r, g, b = classColor.r, classColor.g, classColor.b
		elseif ( IsTapDenied(unitFrame) ) then
			r, g, b = .6, .6, .6
		else
			r, g, b = UnitSelectionColor(unit, true)
			if status and cfg.tankMode then
				if status == 3 then
					r, g, b = 1, 0, 1
				elseif status == 2 or status == 1 then
					r, g, b = 1, 1, 0
				end
			end
		end
	end
	
	if ( r ~= unitFrame.r or g ~= unitFrame.g or b ~= unitFrame.b ) then
		hp:SetStatusBarColor(r, g, b)
		unitFrame.r, unitFrame.g, unitFrame.b = r, g, b
	end

	--[[if not cfg.tankMode then
		if status == 3 then
			hp.shadow:SetBackdropBorderColor(1, 0, 0)
		elseif status == 2 or status == 1 then
			hp.shadow:SetBackdropBorderColor(1, 1, 0)
		else
			hp.shadow:SetBackdropBorderColor(0, 0, 0)
		end
	end]]--
end

local function UpdateCastBar(unitFrame)
	local cb = unitFrame.castBar
	cb.startCastColor = CreateColor(.37, .71, 1)
	cb.startChannelColor = CreateColor(.37, .71, 1)
	cb.finishedCastColor = CreateColor(.1, .8, 0)
	cb.failedCastColor = CreateColor(1, .1, 0)
	cb.nonInterruptibleColor = CreateColor(.78, .25, .25)
	CastingBarFrame_AddWidgetForFade(cb, cb.BorderShield)

	--Disable castbar on PlayerPlate
	local unit
	if not UnitIsUnit(unitFrame.displayedUnit, "player") then
		unit = unitFrame.displayedUnit
	else
		unit = nil
	end
	CastingBarFrame_SetUnit(cb, unit, false, true)
end

local function UpdateCastbarTimer(cb, curValue)
	local _, maxValue = cb:GetMinMaxValues()
	local last = cb.last and cb.last or 0
	local finish = (curValue > last) and (maxValue - curValue) or curValue
	cb.timer:SetFormattedText("%.1f ", finish)
	cb.last = curValue
end

local function UpdateSelectionHighlight(unitFrame)
	if not cfg.arrow then return end
	local unit = unitFrame.unit
	if UnitIsUnit(unit, "target") and not UnitIsUnit(unit, "player") then
		unitFrame.redarrow:Show()
	else
		unitFrame.redarrow:Hide()
	end

	if unitFrame.iconnumber and unitFrame.iconnumber > 0 then
		if unitFrame.iconnumber > 5 then
			unitFrame.redarrow:SetPoint("BOTTOM", unitFrame.name, "TOP", 0, cfg.auraSize*2 + 3)
		else
			unitFrame.redarrow:SetPoint("BOTTOM", unitFrame.name, "TOP", 0, cfg.auraSize + 3)
		end
	else
		unitFrame.redarrow:SetPoint("BOTTOM", unitFrame.name, "TOP", 0, 0)
	end
end

local function UpdateRaidTarget(unitFrame)
	local icon = unitFrame.RaidTargetFrame.RaidTargetIcon
	local index = GetRaidTargetIndex(unitFrame.displayedUnit)
	if ( index ) then
		SetRaidTargetIconTexture(icon, index)
		icon:Show()
	else
		icon:Hide()
	end
end

local function UpdateInVehicle(unitFrame)
	if ( UnitHasVehicleUI(unitFrame.unit) ) then
		if ( not unitFrame.inVehicle ) then
			unitFrame.inVehicle = true
			local prefix, id, suffix = string.match(unitFrame.unit, "([^%d]+)([%d]*)(.*)")
			unitFrame.displayedUnit = prefix.."pet"..id..suffix
			UpdateNamePlateEvents(unitFrame)
		end
	else
		if ( unitFrame.inVehicle ) then
			unitFrame.inVehicle = false
			unitFrame.displayedUnit = unitFrame.unit
			UpdateNamePlateEvents(unitFrame)
		end
	end
end

local function UpdateAll(unitFrame)
	UpdateInVehicle(unitFrame)
	if ( UnitExists(unitFrame.displayedUnit) ) then
		UpdateCastBar(unitFrame)
		UpdateSelectionHighlight(unitFrame)
		UpdateName(unitFrame)
		UpdateHealthColor(unitFrame)
		UpdateHealth(unitFrame)
		UpdateBuffs(unitFrame)
		UpdateRaidTarget(unitFrame)
	end
end

local function NamePlate_OnEvent(self, event, ...)
	local arg1, arg2, arg3, arg4 = ...
	if ( event == "PLAYER_TARGET_CHANGED" ) then
		UpdateName(self)
		UpdateSelectionHighlight(self)
	elseif ( event == "PLAYER_ENTERING_WORLD" ) then
		UpdateAll(self)
	elseif ( arg1 == self.unit or arg1 == self.displayedUnit ) then
		if ( event == "UNIT_HEALTH_FREQUENT" ) then
			UpdateHealth(self)
			UpdateSelectionHighlight(self)
		elseif ( event == "UNIT_AURA" ) then
			UpdateBuffs(self)
			UpdateSelectionHighlight(self)
		elseif ( event == "UNIT_THREAT_SITUATION_UPDATE" ) then
			UpdateHealthColor(self)
		elseif ( event == "UNIT_NAME_UPDATE" ) then
			UpdateName(self)
		elseif ( event == "UNIT_ENTERED_VEHICLE" or event == "UNIT_EXITED_VEHICLE" or event == "UNIT_PET" ) then
			UpdateAll(self)
		end
	end
end

local function UpdateNamePlateEvents(unitFrame)
	-- These are events affected if unit is in a vehicle
	local unit = unitFrame.unit
	local displayedUnit
	if ( unit ~= unitFrame.displayedUnit ) then
		displayedUnit = unitFrame.displayedUnit
	end
	unitFrame:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", unit, displayedUnit)
	unitFrame:RegisterUnitEvent("UNIT_AURA", unit, displayedUnit)
	unitFrame:RegisterUnitEvent("UNIT_THREAT_SITUATION_UPDATE", unit, displayedUnit)
end

local function RegisterNamePlateEvents(unitFrame)
	unitFrame:RegisterEvent("UNIT_NAME_UPDATE")
	unitFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
	unitFrame:RegisterEvent("PLAYER_TARGET_CHANGED")
	unitFrame:RegisterEvent("UNIT_PET")
	unitFrame:RegisterEvent("UNIT_ENTERED_VEHICLE")
	unitFrame:RegisterEvent("UNIT_EXITED_VEHICLE")
	UpdateNamePlateEvents(unitFrame)
	unitFrame:SetScript("OnEvent", NamePlate_OnEvent)
end

local function UnregisterNamePlateEvents(unitFrame)
	unitFrame:UnregisterAllEvents()
	unitFrame:SetScript("OnEvent", nil)
end

local function SetUnit(unitFrame, unit)
	unitFrame.unit = unit
	unitFrame.displayedUnit = unit	 -- For vehicles
	unitFrame.inVehicle = false
	if ( unit ) then
		RegisterNamePlateEvents(unitFrame)
	else
		UnregisterNamePlateEvents(unitFrame)
	end
end

-- Driver frame
local function HideBlizzard()
	NamePlateDriverFrame:UnregisterAllEvents()
	local checkBox = InterfaceOptionsNamesPanelUnitNameplatesMakeLarger
	function checkBox.setFunc(value)
		if value == "1" then
			SetCVar("NamePlateHorizontalScale", checkBox.largeHorizontalScale)
			SetCVar("NamePlateVerticalScale", checkBox.largeVerticalScale)
		else
			SetCVar("NamePlateHorizontalScale", checkBox.normalHorizontalScale)
			SetCVar("NamePlateVerticalScale", checkBox.normalVerticalScale)
		end
		NamePlates_UpdateNamePlateOptions()
	end
	-- CVars
	SetCVar("nameplateShowAll", 1)
	SetCVar("nameplateMaxDistance", 42)			--60
	SetCVar("nameplateOtherTopInset", -1)		--.08
	SetCVar("nameplateOtherBottomInset", -1)	--.1
	-- No more smallplates
	SetCVar("NamePlateHorizontalScale", checkBox.largeHorizontalScale)
	SetCVar("NamePlateVerticalScale", checkBox.largeVerticalScale)
end

local function OnUnitFactionChanged(unit)
	-- This would make more sense as a unitFrame:RegisterUnitEvent
	local namePlate = C_NamePlate.GetNamePlateForUnit(unit)
	if (namePlate) then
		UpdateName(namePlate.UnitFrame)
		UpdateHealthColor(namePlate.UnitFrame)
	end
end

local function OnRaidTargetUpdate()
	for _, namePlate in pairs(C_NamePlate.GetNamePlates()) do
		UpdateRaidTarget(namePlate.UnitFrame)
	end
end

function NamePlates_UpdateNamePlateOptions()
	-- Called at VARIABLES_LOADED and by "Larger Nameplates" interface options checkbox
	local baseNamePlateWidth = cfg.width
	local baseNamePlateHeight = 45
	local horizontalScale = tonumber(GetCVar("NamePlateHorizontalScale"))
	C_NamePlate.SetNamePlateFriendlySize(baseNamePlateWidth * horizontalScale, baseNamePlateHeight)
	C_NamePlate.SetNamePlateEnemySize(baseNamePlateWidth * horizontalScale, baseNamePlateHeight)
	C_NamePlate.SetNamePlateSelfSize(baseNamePlateWidth, baseNamePlateHeight)

	for i, namePlate in ipairs(C_NamePlate.GetNamePlates()) do
		local unitFrame = namePlate.UnitFrame
		UpdateAll(unitFrame)
	end
end

local function OnNamePlateCreated(namePlate)
	local unitFrame = CreateFrame("Button", "$parentUnitFrame", namePlate)
	unitFrame:SetAllPoints(namePlate)
	unitFrame:SetFrameLevel(namePlate:GetFrameLevel())
	namePlate.UnitFrame = unitFrame

	local hp = CreateFrame("StatusBar", nil, unitFrame)
	hp:SetSize(cfg.width, cfg.height)
	hp:SetPoint("LEFT", unitFrame, 0, 0)
	hp:SetPoint("RIGHT", unitFrame, 0, 0)
	hp:SetStatusBarTexture(C.Media.Texture.status)
	hp:SetMinMaxValues(0, 1)
	--hp:CreateShadow()
	unitFrame.healthBar = hp

	hp.bg = hp:CreateTexture(nil, "BORDER")
	hp.bg:SetPoint("TOPLEFT", hp,"TOPLEFT", -26, 10)
    hp.bg:SetPoint("BOTTOMRIGHT", hp, "BOTTOMRIGHT", 26, -10)
	hp.bg:SetTexture(bar_border)
	
	local name = unitFrame:CreateFontString(nil, "OVERLAY")
	name:SetPoint("TOPLEFT", hp, "TOPLEFT", 5, 5)
	name:SetPoint("BOTTOMRIGHT", hp, "TOPRIGHT", -5, 15)
	name:SetWordWrap(false)
	name:SetFont(unpack(C.Media.standard_font))
	name:SetTextColor(1, 1, 1)
	name:SetText("Name")
	unitFrame.name = name

	local hpval = hp:CreateFontString(nil, "OVERLAY")
	hpval:SetPoint("RIGHT", hp, "TOPRIGHT", 0, 2)
	hpval:SetFont(unpack(C.Media.standard_font))
	hpval:SetTextColor(1, 1, 1)
	hpval:SetText("Value")
	hp.value = hpval

	local cb = CreateFrame("StatusBar", nil, unitFrame)
	cb:Hide()
	cb.iconWhenNoninterruptible = false
	cb:SetHeight(5)
	cb:SetPoint("TOPLEFT", hp, "BOTTOMLEFT", 0, -5)
	cb:SetPoint("TOPRIGHT", hp, "BOTTOMRIGHT", 0, -5)
	cb:SetStatusBarTexture(C.Media.Texture.status)
	cb:SetStatusBarColor(.5, .5, .5)
	cb:CreateShadow()
	unitFrame.castBar = cb

	cb.bg = cb:CreateTexture(nil, "BORDER")
	cb.bg:SetAllPoints(cb)
	cb.bg:SetColorTexture(0, 0, 0, .5)

	local cbtext = cb:CreateFontString(nil, "OVERLAY")
	cbtext:SetPoint("CENTER", 0, -5)
	cbtext:SetFont(unpack(C.Media.standard_font))
	cbtext:SetText("Spell Name")
	cb.Text = cbtext

	local timer = cb:CreateFontString (nil, "OVERLAY")
	timer:SetPoint("RIGHT", cb, "BOTTOMRIGHT", 0, -1)
	timer:SetFont(unpack(C.Media.standard_font))
	timer:SetText("Spell Timer")
	cb.timer = timer

	local cbicon = cb:CreateTexture(nil, "OVERLAY", 1)
	cbicon:SetPoint("BOTTOMRIGHT", cb, "BOTTOMLEFT", -4, -1)
	cbicon:SetTexCoord(unpack(C.Media.texCoord))
	cbicon:SetSize(20, 20)
	cb.Icon = cbicon

	local cbibd = cb:CreateTexture(nil, "BACKGROUND")
	cbibd:SetPoint("TOPLEFT", cbicon, -1.2, 1.2)
	cbibd:SetPoint("BOTTOMRIGHT", cbicon, 1.2, -1.2)
	cbibd:SetTexture(C.Media.Texture.status)
	cbibd:SetVertexColor(0, 0, 0)
	cbicon.iconborder = cbibd

	local cbshield = cb:CreateTexture(nil, "OVERLAY", 1)
	cbshield:SetAtlas("nameplates-InterruptShield")
	cbshield:SetSize(15, 15)
	cbshield:SetPoint("LEFT", cb, "LEFT", 5, -5)
	cb.BorderShield = cbshield

	local spark = cb:CreateTexture(nil, "OVERLAY")
	spark:SetSize(30, 25)
	spark:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark")
	spark:SetBlendMode("ADD")
	spark:SetPoint("CENTER")
	cb.Spark = spark

	local flash = cb:CreateTexture(nil, "OVERLAY")
	flash:SetAllPoints()
	flash:SetTexture(C.Media.Texture.status)
	flash:SetBlendMode("ADD")
	cb.Flash = flash

	CastingBarFrame_OnLoad(cb, nil, false, true)
	cb:SetScript("OnEvent", CastingBarFrame_OnEvent)
	cb:SetScript("OnUpdate", CastingBarFrame_OnUpdate)
	cb:SetScript("OnShow", CastingBarFrame_OnShow)
	cb:HookScript("OnValueChanged", UpdateCastbarTimer)

	local rtf = CreateFrame("Frame", nil, unitFrame)
	rtf:SetSize(30, 30)
	rtf:SetPoint("RIGHT", name, "LEFT")
	unitFrame.RaidTargetFrame = rtf

	local ricon = rtf:CreateTexture(nil, "OVERLAY")
	ricon:SetTexture([[Interface\TargetingFrame\UI-RaidTargetingIcons]])
	ricon:SetAllPoints()
	ricon:Hide()
	rtf.RaidTargetIcon = ricon

	local arrow = unitFrame:CreateTexture("$parent_Arrow", "OVERLAY")
	arrow:SetSize(50, 50)
	arrow:SetTexture(C.Media.Nameplate.arrow)
	arrow:SetPoint("CENTER")
	arrow:Hide()
	unitFrame.redarrow = arrow

	local icons = CreateFrame("Frame", nil, unitFrame)
	icons:SetPoint("BOTTOM", unitFrame, "TOP", 0, 0)
	icons:SetWidth(140)
	icons:SetHeight(25)
	icons:SetFrameLevel(unitFrame:GetFrameLevel() + 2)
	unitFrame.icons = icons

	unitFrame:EnableMouse(false)
end

local function OnNamePlateAdded(unit)
	local namePlate = C_NamePlate.GetNamePlateForUnit(unit)
	local unitFrame = namePlate.UnitFrame
	SetUnit(unitFrame, unit)
	UpdateAll(unitFrame)
end

local function OnNamePlateRemoved(unit)
	local namePlate = C_NamePlate.GetNamePlateForUnit(unit)
	SetUnit(namePlate.UnitFrame, nil)
end

local function NamePlates_OnEvent(self, event, ...)
	if ( event == "VARIABLES_LOADED" ) then
		HideBlizzard()
		RedrawManaBar()
		hooksecurefunc(NamePlateDriverFrame, "SetupClassNameplateBar", MoveClassResource)
		NamePlates_UpdateNamePlateOptions()
	elseif ( event == "NAME_PLATE_CREATED" ) then
		local namePlate = ...
		OnNamePlateCreated(namePlate)
	elseif ( event == "NAME_PLATE_UNIT_ADDED" ) then 
		local unit = ...
		OnNamePlateAdded(unit)
	elseif ( event == "NAME_PLATE_UNIT_REMOVED" ) then 
		local unit = ...
		OnNamePlateRemoved(unit)
	elseif event == "RAID_TARGET_UPDATE" then
		OnRaidTargetUpdate()
	elseif event == "DISPLAY_SIZE_CHANGED" then
		NamePlates_UpdateNamePlateOptions()
	elseif ( event == "UNIT_FACTION" ) then
		OnUnitFactionChanged(...)
	elseif cfg.combat then
		if event == "PLAYER_REGEN_ENABLED" then
			SetCVar("nameplateShowEnemies", 0)
		elseif event == "PLAYER_REGEN_DISABLED" then
			SetCVar("nameplateShowEnemies", 1)
		elseif event == "PLAYER_ENTERING_WORLD"	then
			if InCombatLockdown() then
				SetCVar("nameplateShowEnemies", 1)
			else
				SetCVar("nameplateShowEnemies", 0)
			end
			NamePlatesFrame:UnregisterEvent("PLAYER_ENTERING_WORLD")
		end
	end
end

local NamePlatesFrame = CreateFrame("Frame", "NamePlatesFrame", UIParent) 

NamePlatesFrame:SetScript("OnEvent", NamePlates_OnEvent)
NamePlatesFrame:RegisterEvent("VARIABLES_LOADED")
NamePlatesFrame:RegisterEvent("NAME_PLATE_CREATED")
NamePlatesFrame:RegisterEvent("NAME_PLATE_UNIT_ADDED")
NamePlatesFrame:RegisterEvent("NAME_PLATE_UNIT_REMOVED")
NamePlatesFrame:RegisterEvent("DISPLAY_SIZE_CHANGED")
NamePlatesFrame:RegisterEvent("RAID_TARGET_UPDATE")
NamePlatesFrame:RegisterEvent("UNIT_FACTION")
NamePlatesFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
NamePlatesFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
NamePlatesFrame:RegisterEvent("PLAYER_ENTERING_WORLD")