local Range = {
	friendly = {
		["PRIEST"] = {
			(GetSpellInfo(527)), -- Purify
			(GetSpellInfo(17)), -- Power Word: Shield
		},
		["DRUID"] = {
			(GetSpellInfo(774)), -- Rejuvenation
			(GetSpellInfo(2782)), -- Remove Corruption
		},
		["PALADIN"] = GetSpellInfo(19750), -- Flash of Light
		["SHAMAN"] = GetSpellInfo(8004), -- Healing Surge
		["WARLOCK"] = GetSpellInfo(5697), -- Unending Breath
		["DEATHKNIGHT"] = GetSpellInfo(47541), -- Death Coil
		["MONK"] = GetSpellInfo(115450), -- Detox
	},
	hostile = {
		["DEATHKNIGHT"] = {
			(GetSpellInfo(47541)), -- Death Coil
			(GetSpellInfo(49576)), -- Death Grip
		},
		["DEMONHUNTER"] = GetSpellInfo(185123), -- Throw Glaive
		["DRUID"] = GetSpellInfo(8921),  -- Moonfire
		["HUNTER"] = {
			(GetSpellInfo(193455)), -- Cobra Shot
			(GetSpellInfo(19434)), -- Aimed Short
			(GetSpellInfo(193265)), -- Hatchet Toss
		},
		["MAGE"] = {
			(GetSpellInfo(116)), -- Frostbolt
			(GetSpellInfo(30451)), -- Arcane Blast
			(GetSpellInfo(133)), -- Fireball
		},
		["MONK"] = GetSpellInfo(115546), -- Provoke
		["PALADIN"] = GetSpellInfo(20271), -- Judgement
		["PRIEST"] = GetSpellInfo(585), -- Smite
		--["ROGUE"] = GetSpellInfo(1725), -- Distract
		["SHAMAN"] = GetSpellInfo(403), -- Lightning Bolt
		["WARLOCK"] = GetSpellInfo(689), -- Drain Life
		["WARRIOR"] = GetSpellInfo(355), -- Taunt
	},
}

ShadowUF:RegisterModule(Range, "range", ShadowUF.L["Range indicator"])

local LSR = LibStub("SpellRange-1.0")

local playerClass = select(2, UnitClass("player"))
local rangeSpells = {}

local function checkRange(self)
	local frame = self.parent

	-- Check which spell to use
	local spell
	if( UnitCanAssist("player", frame.unit) ) then
		spell = rangeSpells.friendly
	elseif( UnitCanAttack("player", frame.unit) ) then
		spell = rangeSpells.hostile
	end

	if( not UnitIsConnected(frame.unit) ) then
		frame:SetRangeAlpha(ShadowUF.db.profile.units[frame.unitType].range.oorAlpha)
	elseif( spell ) then
		frame:SetRangeAlpha(LSR.IsSpellInRange(spell, frame.unit) == 1 and ShadowUF.db.profile.units[frame.unitType].range.inAlpha or ShadowUF.db.profile.units[frame.unitType].range.oorAlpha)
	-- That didn't work, but they are grouped lets try the actual API for this, it's a bit flaky though and not that useful generally
	elseif( UnitInRaid(frame.unit) or UnitInParty(frame.unit) ) then
		frame:SetRangeAlpha(UnitInRange(frame.unit, "player") and ShadowUF.db.profile.units[frame.unitType].range.inAlpha or ShadowUF.db.profile.units[frame.unitType].range.oorAlpha)
	-- Nope, fall back to interaction :(
	else
		frame:SetRangeAlpha(CheckInteractDistance(frame.unit, 1) and ShadowUF.db.profile.units[frame.unitType].range.inAlpha or ShadowUF.db.profile.units[frame.unitType].range.oorAlpha)
	end
end

local function updateSpellCache(category)
	rangeSpells[category] = nil
	if( IsUsableSpell(ShadowUF.db.profile.range[category .. playerClass]) ) then
		rangeSpells[category] = ShadowUF.db.profile.range[category .. playerClass]

	elseif( IsUsableSpell(ShadowUF.db.profile.range[category .. "Alt" .. playerClass]) ) then
		rangeSpells[category] = ShadowUF.db.profile.range[category .. "Alt" .. playerClass]

	elseif( Range[category][playerClass] ) then
		if( type(Range[category][playerClass]) == "table" ) then
			for i = 1, #Range[category][playerClass] do
				local spell = Range[category][playerClass][i]
				if( IsUsableSpell(spell) ) then
					rangeSpells[category] = spell
					break
				end
			end
		elseif( IsUsableSpell(Range[category][playerClass]) ) then
			rangeSpells[category] = Range[category][playerClass]
		end
	end
end

function Range:ForceUpdate(frame)
	if( UnitIsUnit(frame.unit, "player") ) then
		frame:SetRangeAlpha(ShadowUF.db.profile.units[frame.unitType].range.inAlpha)
		frame.range.timer:Stop()
	else
		frame.range.timer:Play()
		checkRange(frame.range.timer)
	end
end

function Range:OnEnable(frame)
	if( not frame.range ) then
		frame.range = CreateFrame("Frame", nil, frame)

		frame.range.timer = frame:CreateOnUpdate(0.50, checkRange)
		frame.range.timer.parent = frame
	end

	frame:RegisterNormalEvent("PLAYER_SPECIALIZATION_CHANGED", self, "SpellChecks")
	frame:RegisterUpdateFunc(self, "ForceUpdate")

	frame.range.timer:Play()
end

function Range:OnLayoutApplied(frame)
	self:SpellChecks(frame)
end

function Range:OnDisable(frame)
	frame:UnregisterAll(self)
	
	if( frame.range ) then
		frame.range.timer:Stop()
		frame:SetRangeAlpha(1.0)
	end
end


function Range:SpellChecks(frame)
	updateSpellCache("friendly")
	updateSpellCache("hostile")
	if( frame.range ) then
		checkRange(frame.range.timer)
	end
end