local colorbyclass = true									-- 血条按职业着色
local iURCEnable = true										-- 队友/目标/焦点超出治疗范围，框体变淡（仅作用于治疗职业）
local showPlayerSpeed = true								-- 显示玩家移动速度
local showTargetSpeed = true								-- 显示目标移动速度

local function textUpdate(bar)
	if bar then													-- Party Pet frames don't have a mana bar.
		local textType = GetCVar("statusTextDisplay")
		local frame = bar.unitFrame
		if not frame or not frame.addPctText then return end
		local value = bar:GetValue()
		local _, max = bar:GetMinMaxValues()
		if bar.pctText then
			if textType ~= "NUMERIC" then
				bar.pctText:SetText("")
			elseif value == 0 then
				bar.pctText:SetText((bar.DeadText or bar.TextString) and "" or DEAD)
			else
				bar.pctText:SetText(tostring(math.ceil((value / max) * 100)) .. "%")
			end
		end
		if bar.TextString and textType == "NUMERIC" and value > 0 then
			if bar.capNumericDisplay then
				value = AbbreviateLargeNumbers(value)
			else
				value = BreakUpLargeNumbers(value)
			end
			bar.TextString:SetText(value)
		end
	end
end

local function colorHPBar(bar, unit)
	if bar and not bar.lockValues and unit == bar.unit then
		local r, g, b
		local min, max = bar:GetMinMaxValues()
		local value = bar:GetValue()
		if max > min then
			value = (value - min) / (max - min)
		else
			value = 0
		end
		if value > 0.5 then
			r, g, b = 2*(1-value), 1, 0
		else
			r, g, b = 1, 2*value, 0
		end
		if bar.pctText then bar.pctText:SetTextColor(r, g, b) end
		if colorbyclass then
			if UnitIsPlayer(unit) and UnitClass(unit) then
				local color = RAID_CLASS_COLORS[select(2, UnitClass(unit))]
				bar:SetStatusBarColor(color.r, color.g, color.b)
				bar:SetStatusBarDesaturated(true)
			else
				bar:SetStatusBarColor(0, 0.9, 0.3)			-- defaultColor
				bar:SetStatusBarDesaturated(false)
			end
		end
	end
end

hooksecurefunc("UnitFrameHealthBar_OnUpdate", textUpdate)
hooksecurefunc("UnitFrameManaBar_OnUpdate", textUpdate)
hooksecurefunc("UnitFrameManaBar_Update", textUpdate)
hooksecurefunc("UnitFrameHealthBar_Update", colorHPBar)
hooksecurefunc("HealthBar_OnValueChanged", function(self) colorHPBar(self, self.unit) end)


function SetNameColor(frame)
	if frame.name and frame.unit then
		local color = UnitIsPlayer(frame.unit) and RAID_CLASS_COLORS[select(2, UnitClass(frame.unit))] or NORMAL_FONT_COLOR
		frame.name:SetTextColor(color.r, color.g, color.b)
	end
end

hooksecurefunc("UnitFrame_Update", function(self)
	if self.name and self.unit then
		SetNameColor(self)
	end
end)


function CreateBarPctText(frame, ap, rp, x, y, height)
	local bar = frame.healthbar
	if bar then
		bar.pctText = frame:CreateFontString(nil, "OVERLAY", "NumberFontNormal")
		bar.pctText:SetPoint(ap, bar, rp, x, y)
		bar.pctText:SetTextHeight(height or 12)
		frame.addPctText = true
	end
end

function CreateClassIcon(parent, scale, ap, rp, x, y)
	local icon = CreateFrame("Button", nil, parent)
	icon:Hide()
	icon:SetWidth(31*scale)
	icon:SetHeight(31*scale)
	icon:SetFrameLevel(parent:GetFrameLevel()+3)
	icon:SetPoint(ap, parent, rp, x, y)

	icon.tex = icon:CreateTexture(nil, "BACKGROUND")
	icon.tex:SetWidth(20*scale)
	icon.tex:SetHeight(20*scale)
	icon.tex:SetTexture("Interface\\TargetingFrame\\UI-Classes-Circles")
	icon.tex:SetPoint("CENTER")

	icon.lay = icon:CreateTexture(nil, "OVERLAY")
	icon.lay:SetWidth(54*scale)
	icon.lay:SetHeight(54*scale)
	icon.lay:SetTexture("Interface\\Minimap\\MiniMap-TrackingBorder")
	icon.lay:SetPoint("TOPLEFT")

	return icon
end


---------------------
------ Frames -------
---------------------

CreateBarPctText(PlayerFrame, "LEFT", "RIGHT", 4, 0, 14)
PlayerName:SetTextHeight(13)

CreateBarPctText(PetFrame, "LEFT", "RIGHT", 4, 0)
PetName:SetTextHeight(12)
PetFrameHealthBarText:SetTextHeight(9)
PetFrameManaBarText:SetTextHeight(9)

CreateBarPctText(TargetFrame, "RIGHT", "LEFT", -4, 0, 14)
TargetFrame.TargetFrameContent.TargetFrameContentMain.Name:SetTextHeight(13)
TargetFrame.TargetFrameContent.TargetFrameContentContextual.NumericalThreat.text:SetTextHeight(10)
CreateBarPctText(TargetFrameToT, "BOTTOMRIGHT", "TOPRIGHT", 0, 16)
TargetFrameToT.Name:SetTextHeight(12)

CreateBarPctText(FocusFrame, "RIGHT", "LEFT", 0, 0, 13)
CreateBarPctText(FocusFrameToT, "BOTTOMRIGHT", "TOPRIGHT", 0, 15)

for i = 1, MAX_BOSS_FRAMES do
	local bossFrame = _G["Boss"..i.."TargetFrame"]
	CreateBarPctText(bossFrame, "BOTTOMLEFT", "TOPRIGHT", 17, 17, 14)
	bossFrame.TargetFrameContent.TargetFrameContentContextual.NumericalThreat.text:SetTextHeight(10)
end

TargetFrame.icon = CreateClassIcon(TargetFrame, 1, "TOPRIGHT", "TOPRIGHT", -14, -5)
TargetFrame.icon:SetScript("OnClick", function()
	if InCombatLockdown() then return end
	if IsAltKeyDown() then InitiateTrade("target") else InspectUnit("target") end 
end)
TargetFrame.type = TargetFrame:CreateFontString(nil, "OVERLAY", "ReputationDetailFont")
TargetFrame.type:SetPoint("BOTTOM", TargetFrame.icon, "TOP")

hooksecurefunc(TargetFrame, "Update", function(self)
	if not UnitExists(self.unit) then return end
	local type, color
	if UnitIsPlayer(self.unit) then
		if self.icon then
			local coord = CLASS_ICON_TCOORDS[select(2, UnitClass(self.unit))]
			self.icon.tex:SetTexCoord(unpack(coord))
			self.icon:Show()
		end
		type = UnitRace(self.unit)
		if UnitFactionGroup(self.unit) == UnitFactionGroup("player") then
			color = GREEN_FONT_COLOR
		else
			color = RED_FONT_COLOR
		end
	else
		if self.icon then self.icon:Hide() end
		type = UnitCreatureType(self.unit) or ""
		if UnitCanAttack(self.unit, "player") then
			color = UnitPlayerControlled(self.unit) and ORANGE_FONT_COLOR or YELLOW_FONT_COLOR
		else
			color = HIGHLIGHT_FONT_COLOR
		end
	end
	if self.type then
		self.type:SetText(type)
		self.type:SetTextColor(color.r, color.g, color.b)
	end
end)


-- Check Party Unit within ~40 Yards of the Player
-- and Target/Focus Range Check for Healers
-- and Show Speed of Player and Target

local hasTarget, updateElapsed, lastPlayerSpeed, lastTargetSpeed

local healingSpell = { ["德鲁伊"]   = "回春术",
					   ["牧师"]     = "快速治疗",
					   ["圣骑士"]   = "圣光闪现",
					   ["萨满祭司"] = "治疗之涌",
					   ["武僧"]     = "活血术",
					   ["唤魔师"]   = "活化烈焰"  }
local iURCSpell = healingSpell[UnitClass("player")] or nil

local function rangeCheck(frame, isParty)
	if not frame:IsShown() or not frame.unit then return end
	local outRange
	if isParty then
		if UnitIsUnit(frame.unit, PlayerFrame.unit) then return end		-- not work in editmode without party
		outRange = not UnitInRange(frame.unit)
	else
		if not iURCSpell then return end											-- valid for Healers only
		outRange = C_Spell.IsSpellInRange(iURCSpell, frame.unit) == false
	end
	if outRange then
		frame:SetAlpha(0.5)
	else
		frame:SetAlpha(1)
	end
end

local function GetSpeedText(speed)
	local text = ""
	if speed and speed > 0 then
		text = format("|cffffff00%d%%|r", speed * 100 / 7 + 0.5)
	end
	return text
end

local iFrame = CreateFrame("Frame")
iFrame:RegisterEvent("PLAYER_TARGET_CHANGED")

iFrame:SetScript("OnEvent", function(self, event, ...)
	if event == "PLAYER_TARGET_CHANGED" then
		hasTarget = UnitExists("target") and not UnitIsUnit("vehicle", "target")
	end
end)

PlayerFrame.speed = PlayerFrame:CreateFontString(nil, "OVERLAY", "NumberFontNormal")
PlayerFrame.speed:SetPoint("LEFT", PlayerFrame.manabar, "RIGHT", 5, 0)
TargetFrame.speed = TargetFrame:CreateFontString(nil, "OVERLAY", "NumberFontNormal")
TargetFrame.speed:SetPoint("RIGHT", TargetFrame.manabar, "LEFT", -5, 0)

iFrame:SetScript("OnUpdate", function(self, elapsed)
	updateElapsed = (updateElapsed or 0) + elapsed
	if updateElapsed > TOOLTIP_UPDATE_TIME then
		updateElapsed = 0
		if iURCEnable then
			rangeCheck(TargetFrame)
			rangeCheck(FocusFrame)
			for frame in PartyFrame.PartyMemberFramePool:EnumerateActive() do
				rangeCheck(frame, true)
			end
		end
		if showPlayerSpeed then
			local isGliding, canGlide, forwardSpeed = C_PlayerInfo.GetGlidingInfo()
			local playerSpeed = isGliding and forwardSpeed or GetUnitSpeed(PlayerFrame.unit)
			if lastPlayerSpeed ~= playerSpeed then
				lastPlayerSpeed = playerSpeed
				PlayerFrame.speed:SetText(GetSpeedText(playerSpeed))
			end
		end
		if showTargetSpeed then
			local targetSpeed = hasTarget and GetUnitSpeed("target") or nil
			if lastTargetSpeed ~= targetSpeed then
				lastTargetSpeed = targetSpeed
				TargetFrame.speed:SetText(GetSpeedText(targetSpeed))
			end
		end
	end
end)
