LEVEL_UP_TYPE_CHARACTER = "character";	--Name used in globalstring LEVEL_UP
LEVEL_UP_TYPE_GUILD = "guild";	--Name used in globalstring GUILD_LEVEL_UP
LEVEL_UP_TYPE_PET = "pet" -- Name used in globalstring PET_LEVEL_UP
LEVEL_UP_TYPE_SCENARIO = "scenario";
LEVEL_UP_TYPE_SPELL_BUCKET = "spellbucket";
TOAST_QUEST_BOSS_EMOTE = "questbossemote";
TOAST_PET_BATTLE_WINNER = "petbattlewinner";
TOAST_PET_BATTLE_CAPTURE = "petbattlecapturetoast";
TOAST_PET_BATTLE_LEVELUP = "petbattleleveluptoast";
TOAST_PET_BATTLE_LOOT = "petbattleloot";
TOAST_CHALLENGE_MODE_RECORD = "challengemode";
TOAST_GARRISON_ABILITY = "garrisonability";

LEVEL_UP_EVENTS = {
--  Level  = {unlock}
	[10] = {"SpecializationUnlocked", "BGsUnlocked"},
	[15] = {"TalentsUnlocked","LFDUnlocked"},
	[25] = {"Glyphs"},
	[30] = {"DualSpec"},
	[50] = {"GlyphSlots"},
	[70] = {"HeroicBurningCrusade"},
	[75] = {"GlyphSlots"},
	[80] = {"HeroicWrathOfTheLichKing"},
	[85] = {"HeroicCataclysm"},
	[90] = {"HeroicMistsOfPandaria"},
}

SUBICON_TEXCOOR_BOOK 	= {0.64257813, 0.72070313, 0.03710938, 0.11132813};
SUBICON_TEXCOOR_LOCK	= {0.64257813, 0.70117188, 0.11523438, 0.18359375};
SUBICON_TEXCOOR_ARROW 	= {0.72460938, 0.78320313, 0.03710938, 0.10351563};

local levelUpTexCoords = {
	[LEVEL_UP_TYPE_CHARACTER] = {
		dot = { 0.64257813, 0.68359375, 0.18750000, 0.23046875 },
		goldBG = { 0.56054688, 0.99609375, 0.24218750, 0.46679688 },
		gLine = { 0.00195313, 0.81835938, 0.01953125, 0.03320313 },
		gLineDelay = 1.5,
	},
	[LEVEL_UP_TYPE_GUILD] = {
		dot = { 0.64257813, 0.68359375, 0.77734375, 0.8203125 },
		goldBG = { 0.56054688, 0.99609375, 0.486328125, 0.7109375 },
		gLine = { 0.00195313, 0.81835938, 0.96484375, 0.97851563 },
		textTint = {0.11765, 1, 0},
		gLineDelay = 1.5,
	},
	[LEVEL_UP_TYPE_PET] = {
		dot = { 0.64257813, 0.68359375, 0.18750000, 0.23046875 },
		goldBG = { 0.56054688, 0.99609375, 0.24218750, 0.46679688 },
		gLine = { 0.00195313, 0.81835938, 0.01953125, 0.03320313 },
		tint = {1, 0.5, 0.25},
		textTint = {1, 0.7, 0.25},
		gLineDelay = 1.5,
	},
	[TOAST_PET_BATTLE_WINNER] = {
		gLine = { 0.00195313, 0.81835938, 0.01953125, 0.03320313 },
		tint = {1, 0.5, 0.25},
		textTint = {1, 0.7, 0.25},
		gLineDelay = 1.5,
	},
	[TOAST_PET_BATTLE_CAPTURE] = {
		gLine = { 0.00195313, 0.81835938, 0.01953125, 0.03320313 },
		tint = {1, 0.5, 0.25},
		textTint = {1, 0.7, 0.25},
		gLineDelay = 1.5,
	},
	[TOAST_PET_BATTLE_LEVELUP] = {
		gLine = { 0.00195313, 0.81835938, 0.01953125, 0.03320313 },
		tint = {1, 0.5, 0.25},
		textTint = {1, 0.7, 0.25},
		gLineDelay = 1.5,
	},
	[TOAST_PET_BATTLE_LOOT] = {
		gLine = { 0.00195313, 0.81835938, 0.01953125, 0.03320313 },
		tint = {1, 0.5, 0.25},
		textTint = {1, 0.7, 0.25},
		gLineDelay = 1.5,
	},
	[LEVEL_UP_TYPE_SCENARIO] = {
		gLine = { 0.00195313, 0.81835938, 0.00195313, 0.01562500 },
		tint = {1, 0.996, 0.745},
		gLineDelay = 0,
	},
	[TOAST_QUEST_BOSS_EMOTE] = {
		gLine = { 0.00195313, 0.81835938, 0.01953125, 0.03320313 },
		tint = {1, 0.996, 0.745},
		textTint = {1, 0.7, 0.25},
		gLineDelay = 0,
	},
	[TOAST_CHALLENGE_MODE_RECORD] = {
		gLine = { 0.00195313, 0.81835938, 0.00195313, 0.01562500 },
		tint = {0.777, 0.698, 0.451},
		gLineDelay = 0,
	},
	[TOAST_GARRISON_ABILITY] = {
		dot = { 0.64257813, 0.68359375, 0.18750000, 0.23046875 },
		goldBG = { 0.56054688, 0.99609375, 0.24218750, 0.46679688 },
		gLine = { 0.00195313, 0.81835938, 0.01953125, 0.03320313 },
		gLineDelay = 1.5,
	},
	[LEVEL_UP_TYPE_SPELL_BUCKET] = {
		dot = { 0.64257813, 0.68359375, 0.18750000, 0.23046875 },
		goldBG = { 0.56054688, 0.99609375, 0.24218750, 0.46679688 },
		gLine = { 0.00195313, 0.81835938, 0.01953125, 0.03320313 },
		gLineDelay = 1.5,
	},
}

LEVEL_UP_TYPES = {
	["TalentPoint"] 			=	{	icon="Interface\\Icons\\Ability_Marksmanship",
										subIcon=SUBICON_TEXCOOR_ARROW,
										text=LEVEL_UP_TALENT_MAIN,
										subText=LEVEL_UP_TALENT_SUB,
										link=LEVEL_UP_TALENTPOINT_LINK;
									},
	
	["PetTalentPoint"] 			=	{	icon="Interface\\Icons\\Ability_Marksmanship",
										subIcon=SUBICON_TEXCOOR_ARROW,
										text=PET_LEVEL_UP_TALENT_MAIN,
										subText=PET_LEVEL_UP_TALENT_SUB,
										link=PET_LEVEL_UP_TALENTPOINT_LINK;
									},
									
	["SpecializationUnlocked"] 	= 	{	icon="Interface\\Icons\\Ability_Marksmanship",
										subIcon=SUBICON_TEXCOOR_LOCK,
										text=SPECIALIZATION,
										subText=LEVEL_UP_FEATURE,
										link=LEVEL_UP_FEATURE2..LEVEL_UP_SPECIALIZATION_LINK
									},
									
	["TalentsUnlocked"] 		= 	{	icon="Interface\\Icons\\Ability_Marksmanship",
										subIcon=SUBICON_TEXCOOR_LOCK,
										text=TALENT_POINTS,
										subText=LEVEL_UP_FEATURE,
										link=LEVEL_UP_FEATURE2..LEVEL_UP_TALENTS_LINK
									},
									
	["BGsUnlocked"] 			= 	{	icon="Interface\\Icons\\Ability_DualWield",
										subIcon=SUBICON_TEXCOOR_LOCK,
										text=BATTLEFIELDS,
										subText=LEVEL_UP_FEATURE,
										link=LEVEL_UP_FEATURE2..LEVEL_UP_BG_LINK
									},

	["LFDUnlocked"] 			= 	{	icon="Interface\\Icons\\LevelUpIcon-LFD",
										subIcon=SUBICON_TEXCOOR_LOCK,
										text=LOOKING_FOR_DUNGEON,
										subText=LEVEL_UP_FEATURE,
										link=LEVEL_UP_FEATURE2..LEVEL_UP_LFD_LINK
									},

	["Glyphs"]					=	{	icon="Interface\\Icons\\Inv_inscription_tradeskill01",
										subIcon=SUBICON_TEXCOOR_LOCK,
										text=GLYPHS,
										subText=LEVEL_UP_FEATURE,
										link=LEVEL_UP_GLYPHSLOT_LINK
									},

	["GlyphSlots"]				= 	{	icon="Interface\\Icons\\Inv_inscription_tradeskill01",
										subIcon=SUBICON_TEXCOOR_LOCK,
										text=GLYPH_SLOTS,
										subText=LEVEL_UP_FEATURE,
										link=LEVEL_UP_GLYPHSLOT_LINK
									},

	["DualSpec"] 				=	{	icon="Interface\\Icons\\INV_Misc_Coin_01",
										subIcon=SUBICON_TEXCOOR_LOCK,
										text=LEVEL_UP_DUALSPEC,
										subText=LEVEL_UP_FEATURE,
										link=LEVEL_UP_FEATURE2..LEVEL_UP_DUAL_SPEC_LINK
									},

	["HeroicBurningCrusade"]	=	{	entryType = "heroicdungeon",
										tier = 2,
										icon="Interface\\Icons\\ExpansionIcon_BurningCrusade",
										subIcon=SUBICON_TEXCOOR_LOCK,
										text=EXPANSION_NAME1,
										subText=LEVEL_UP_HEROIC,
									},
									
	["HeroicWrathOfTheLichKing"]= 	{	entryType = "heroicdungeon",
										tier = 3,
										icon="Interface\\Icons\\ExpansionIcon_WrathoftheLichKing",
										subIcon=SUBICON_TEXCOOR_LOCK,
										text=EXPANSION_NAME2,
										subText=LEVEL_UP_HEROIC,
									},
									
	["HeroicCataclysm"]			=	{	entryType = "heroicdungeon",
										tier = 4,
										icon="Interface\\Icons\\ExpansionIcon_Cataclysm",
										subIcon=SUBICON_TEXCOOR_LOCK,
										text=EXPANSION_NAME3,
										subText=LEVEL_UP_HEROIC,
									},
									
	["HeroicMistsOfPandaria"]	= 	{ 	entryType = "heroicdungeon",
										tier = 5,
										icon="Interface\\Icons\\ExpansionIcon_MistsofPandaria",
										subIcon=SUBICON_TEXCOOR_LOCK,
										text=EXPANSION_NAME4,
										subText=LEVEL_UP_HEROIC
									},
									
------ HACKS BELOW		
 	["Teleports"] 			= {	spellID=109424	},
	["PortalsHorde"]		= {	spellID=109400	},
	["PortalsAlliance"]		= {	spellID=109401	},
									
 	["LockMount1"] 			= {	spellID=5784	},
 	["LockMount2"] 			= {	spellID=23161	},
 	["PaliMountHorde1"] 	= {	spellID=34769	},
 	["PaliMountHorde2"] 	= {	spellID=34767	},
 	["PaliMountAlliance1"] 	= {	spellID=13819	},
 	["PaliMountAlliance2"] 	= {	spellID=23214	},
 	["PaliMountTauren1"] 	= {	spellID=69820	},
 	["PaliMountTauren2"] 	= {	spellID=69826	},
 	["PaliMountDraenei1"] 	= {	spellID=73629	},
 	["PaliMountDraenei2"] 	= {	spellID=73630	},
 	
	["Plate"]	 			= {	spellID=750, feature=true},
	["Mail"] 				= {	spellID=8737, feature=true	},
	
	["TrackBeast"] 			= {	spellID=1494  },
	["TrackHumanoid"] 		= {	spellID=19883  },
	["TrackUndead"] 		= {	spellID=19884  },
	["TrackHidden"] 		= {	spellID=19885  },
	["TrackElemental"] 		= {	spellID=19880  },
	["TrackDemons"] 		= {	spellID=19878 },
	["TrackGiants"] 		= {	spellID=19882  },
	["TrackDragonkin"] 		= {	spellID=19879  },
------ END HACKS
}


LEVEL_UP_CLASS_HACKS = {
	
	["MAGEHorde"] 		= {
							--  Level  = {unlock}
								[24] = {"Teleports"},
								[42] = {"PortalsHorde"},
							},
	["MAGEAlliance"]	= {
							--  Level  = {unlock}
								[24] = {"Teleports"},
								[42] = {"PortalsAlliance"},
							},
	["WARLOCK"] 		= {
							--  Level  = {unlock}
								[20] = {"LockMount1"},
								[40] = {"LockMount2"},
							},
	["SHAMAN"] 		= {
							--  Level  = {unlock}
								[40] = {"Mail"},
							},
	["HUNTER"] 		= {
							--  Level  = {unlock}
								[40] = {"Mail"},
							},
	["WARRIOR"] 		= {
							--  Level  = {unlock}
								[40] = {"Plate"},
							},
	["PALADINHorde"] 		= {
							--  Level  = {unlock}
								[20] = {"PaliMountHorde1"},
								[40] = {"PaliMountHorde2", "Plate"},
							},
	["PALADINAlliance"] 	= {
							--  Level  = {unlock}
								[20] = {"PaliMountAlliance1"},
								[40] = {"PaliMountAlliance2", "Plate"},
							},
	["PALADINTauren"]	= {
							--  Level  = {unlock}
								[20] = {"PaliMountTauren1"},
								[40] = {"PaliMountTauren2", "Plate"},
							},	
	["PALADINDraenei"]	= {
							--  Level  = {unlock}
								[20] = {"PaliMountDraenei1"},
								[40] = {"PaliMountDraenei2", "Plate"},
							},	
}

GARRISON_ABILITY_HACKS = {
	[26] = {
		["Horde"] = 161332,
		["Alliance"] = 161676,
		["Subtext"] = GARRISON_ABILITY_BARRACKS_UNLOCKED,
	},
}

LEVEL_UP_TRAP_LEVELS = {427, 77, 135}

function LevelUpDisplay_OnLoad(self)
	self:RegisterEvent("PLAYER_LEVEL_UP");
	self:RegisterEvent("UNIT_GUILD_LEVEL");
	self:RegisterEvent("UNIT_LEVEL");
	--self:RegisterEvent("SCENARIO_UPDATE");	this is now handled from the ObjectiveTracker
	self:RegisterEvent("PET_BATTLE_FINAL_ROUND"); -- display winner, start listening for additional results
	self:RegisterEvent("PET_BATTLE_CLOSE");        -- stop listening for additional results
	self:RegisterEvent("QUEST_BOSS_EMOTE");
	self:RegisterEvent("CHALLENGE_MODE_NEW_RECORD");
	self:RegisterEvent("PET_JOURNAL_TRAP_LEVEL_SET");
	self:RegisterEvent("PET_BATTLE_LEVEL_CHANGED");
	self:RegisterEvent("PET_BATTLE_CAPTURED");
	self:RegisterEvent("PET_BATTLE_LOOT_RECEIVED");
	self:RegisterEvent("LOADING_SCREEN_ENABLED");
	self:RegisterEvent("LOADING_SCREEN_DISABLED");
	self:RegisterEvent("GARRISON_BUILDING_ACTIVATED");
	self:RegisterEvent("CHARACTER_UPGRADE_SPELL_TIER_SET");
	self.currSpell = 0;
end



function LevelUpDisplay_OnEvent(self, event, ...)
	local arg1 = ...;
	if event == "LOADING_SCREEN_ENABLED" then
		LevelUpDisplay_StopAllAnims(self);
		self:Hide();	--We'll restart this toast on PLAYER_ENTERING_WORLD
		self.currSpell = 0;
	elseif event == "LOADING_SCREEN_DISABLED" then
		if ( self.type ) then
			LevelUpDisplay_Start(self, self.unlockList);
		end
	elseif event ==  "PLAYER_LEVEL_UP" then
		local level = ...
		self.level = level;
		self.type = LEVEL_UP_TYPE_CHARACTER;
		LevelUpDisplay_Show(self);
		LevelUpDisplaySide:Hide();
	elseif event == "UNIT_GUILD_LEVEL" then
		local unit, level = ...;
		if ( unit == "player" ) then
			self.level = level;
			self.type = LEVEL_UP_TYPE_GUILD;
			LevelUpDisplay_Show(self);
			LevelUpDisplaySide:Hide();
		end
	elseif event == "UNIT_LEVEL" and arg1 == "pet" then
		if (UnitName("pet") ~= UNKNOWNOBJECT) then
			self.level = UnitLevel("pet");
			self.type = LEVEL_UP_TYPE_PET;
			LevelUpDisplay_Show(self);
			LevelUpDisplaySide:Hide();
		end
	elseif ( event == "ZONE_CHANGED_NEW_AREA" ) then
		self:UnregisterEvent("ZONE_CHANGED_NEW_AREA");
		if ( self.type or self.queuedType ) then
			LevelUpDisplay_Show(self);
		end
	elseif ( event == "PET_BATTLE_FINAL_ROUND" ) then
		self.type = TOAST_PET_BATTLE_WINNER;
		self.winner = arg1;
		LevelUpDisplay_Show(self);
	elseif ( event == "PET_JOURNAL_TRAP_LEVEL_SET" ) then
		local trapLevel = ...;
		if (trapLevel >= 1 and trapLevel <= #LEVEL_UP_TRAP_LEVELS) then
			LevelUpDisplay_AddBattlePetTrapUpgradeEvent(self, trapLevel);
		end
	elseif ( event == "PET_BATTLE_LEVEL_CHANGED" ) then
		local activePlayer, activePetSlot, newLevel = ...;
		if (activePlayer == LE_BATTLE_PET_ALLY) then
			LevelUpDisplay_AddBattlePetLevelUpEvent(self, activePlayer, activePetSlot, newLevel);
		end
	elseif ( event == "PET_BATTLE_CAPTURED" ) then
		local fromPlayer, activePetSlot = ...;
		if (fromPlayer == LE_BATTLE_PET_ENEMY) then
			LevelUpDisplay_AddBattlePetCaptureEvent(self, fromPlayer, activePetSlot);
		end
	elseif ( event == "PET_BATTLE_LOOT_RECEIVED" ) then
		local typeIdentifier, itemLink, quantity = ...;
		LevelUpDisplay_AddBattlePetLootReward(self, typeIdentifier, itemLink, quantity);
	elseif ( event == "QUEST_BOSS_EMOTE" ) then
		local str, name, displayTime, warningSound = ...;
		self.type = TOAST_QUEST_BOSS_EMOTE;
		self.bossText = format(str, name, name);
		self.time = displayTime;
		self.sound = warningSound;
		LevelUpDisplay_Show(self);
	elseif ( event == "CHALLENGE_MODE_NEW_RECORD" ) then
		local mapID, recordTime, medal = ...;
		self.type = TOAST_CHALLENGE_MODE_RECORD;
		self.mapID = mapID;
		self.recordTime = recordTime;
		self.medal = medal;
		LevelUpDisplay_Show(self);
		PlaySoundKitID(33338);
	elseif ( event == "GARRISON_BUILDING_ACTIVATED" ) then
		local _, buildingID = ...;
		if (GARRISON_ABILITY_HACKS[buildingID]) then
			self.buildingID = buildingID;
			self:RegisterEvent("CINEMATIC_STOP");
		end
	elseif ( event == "CINEMATIC_STOP" ) then
		self.type = TOAST_GARRISON_ABILITY;
		LevelUpDisplay_Show(self);
		self:UnregisterEvent("CINEMATIC_STOP");
	elseif ( event == "CHARACTER_UPGRADE_SPELL_TIER_SET") then
		local tierIndex = ...;
		LevelUpDisplay_AddSpellBucketUnlockEvent(self, tierIndex);
	end
end

function LevelUpDisplay_StopAllAnims(self)
	self.fastHideAnim:Stop();
	self.hideAnim:Stop();
	self.spellFrame.showAnim:Stop();
	self.scenarioFrame.newStage:Stop();
	self.challengeModeFrame.challengeComplete:Stop();
	self.levelFrame.levelUp:Stop();
	self.levelFrame.fastReveal:Stop();
end

function LevelUpDisplay_PlayScenario()
	LevelUpDisplay.type = LEVEL_UP_TYPE_SCENARIO;
	LevelUpDisplay_Show(LevelUpDisplay);
end

function LevelUpDisplay_BuildCharacterList(self)
	local name, icon, link = "","",nil;
	self.unlockList = {};

	if LEVEL_UP_EVENTS[self.level] then
		for _, unlockType in pairs(LEVEL_UP_EVENTS[self.level]) do
			self.unlockList[#self.unlockList +1] = LEVEL_UP_TYPES[unlockType];
		end
	end
	
	local spells = {GetCurrentLevelSpells(self.level)};
	for _,spell in pairs(spells) do		
		name, _, icon = GetSpellInfo(spell);
		self.unlockList[#self.unlockList +1] = { entryType = "spell", text = name, subText = LEVEL_UP_ABILITY, icon = icon, subIcon = SUBICON_TEXCOOR_BOOK,
																link=LEVEL_UP_ABILITY2.." "..GetSpellLink(spell)
															};
	end	

	local GUILD_EVENT_TEXTURE_PATH = "Interface\\LFGFrame\\LFGIcon-";
	local dungeons = {GetLevelUpInstances(self.level, false)};
	for _,dungeon in pairs(dungeons) do
		name, icon, link = GetDungeonInfo(dungeon);
		if link then -- link can come back as nil if there's no Dungeon Journal entry
			self.unlockList[#self.unlockList +1] = { entryType = "dungeon", text = name, subText = LEVEL_UP_DUNGEON, icon = GUILD_EVENT_TEXTURE_PATH..icon, subIcon = SUBICON_TEXCOOR_LOCK,
																		link = LEVEL_UP_DUNGEON2.." "..link
																	};
		else
			self.unlockList[#self.unlockList +1] = { entryType = "dungeon", text = name, subText = LEVEL_UP_DUNGEON, icon = GUILD_EVENT_TEXTURE_PATH..icon, subIcon = SUBICON_TEXCOOR_LOCK,
																		link = LEVEL_UP_DUNGEON2.." "..name
																	};
		end
	end
	
	local raids = {GetLevelUpInstances(self.level, true)};
	for _,raid in pairs(raids) do
		name, icon, link = GetDungeonInfo(raid);
		if link then -- link can come back as nil if there's no Dungeon Journal entry
			self.unlockList[#self.unlockList +1] = { entryType = "dungeon", text = name, subText = LEVEL_UP_RAID, icon = GUILD_EVENT_TEXTURE_PATH..icon, subIcon = SUBICON_TEXCOOR_LOCK,
																		link = LEVEL_UP_RAID2.." "..link
																	};
		else
			self.unlockList[#self.unlockList +1] = { entryType = "dungeon", text = name, subText = LEVEL_UP_RAID, icon = GUILD_EVENT_TEXTURE_PATH..icon, subIcon = SUBICON_TEXCOOR_LOCK,
																		link = LEVEL_UP_RAID2.." "..name
																	};
		end
	end


	-- This loop is LEVEL_UP_CLASS_HACKS
	local race, raceFile = UnitRace("player");
	local _, class = UnitClass("player");
	local factionName = UnitFactionGroup("player");
	local hackTable = LEVEL_UP_CLASS_HACKS[class..raceFile] or LEVEL_UP_CLASS_HACKS[class..factionName] or LEVEL_UP_CLASS_HACKS[class];
	if  hackTable and hackTable[self.level] then
		hackTable = hackTable[self.level];
		for _,spelltype in pairs(hackTable) do
			if LEVEL_UP_TYPES[spelltype] and LEVEL_UP_TYPES[spelltype].spellID then 
				if LEVEL_UP_TYPES[spelltype].feature then
					name, _, icon = GetSpellInfo(LEVEL_UP_TYPES[spelltype].spellID);
					self.unlockList[#self.unlockList +1] = { text = name, subText = LEVEL_UP_FEATURE, icon = icon, subIcon = SUBICON_TEXCOOR_LOCK,
																			link=LEVEL_UP_FEATURE2.." "..GetSpellLink(LEVEL_UP_TYPES[spelltype].spellID)
																		};
				else
					name, _, icon = GetSpellInfo(LEVEL_UP_TYPES[spelltype].spellID);
					self.unlockList[#self.unlockList +1] = { text = name, subText = LEVEL_UP_ABILITY, icon = icon, subIcon = SUBICON_TEXCOOR_BOOK,
																			link=LEVEL_UP_ABILITY2.." "..GetSpellLink(LEVEL_UP_TYPES[spelltype].spellID)
																		};
				end
			end
		end	
	end
	
	
	local features = {GetCurrentLevelFeatures(self.level)};
	for _,feature in pairs(features) do		
		name, _, icon = GetSpellInfo(feature);
		self.unlockList[#self.unlockList +1] = { entryType = "spell", text = name, subText = LEVEL_UP_FEATURE, icon = icon, subIcon = SUBICON_TEXCOOR_LOCK,
																link=LEVEL_UP_FEATURE2.." "..GetSpellLink(feature)
															};
	end	
	
	local draenorTalent = GetCurrentLevelDraenorTalent(self.level);
	if (draenorTalent) then
		name, _, icon = GetSpellInfo(draenorTalent);
		self.unlockList[#self.unlockList +1] = { entryType = "draenortalent", text = name, subText = LEVEL_UP_DRAENORTALENT, icon = icon, subIcon = SUBICON_TEXCOOR_BOOK, description = GetSpellDescription(draenorTalent),
																link=LEVEL_UP_DRAENOR_TALENT2.." "..GetSpellLink(draenorTalent) };
	end

	self.currSpell = 1;
end

function LevelUpDisplay_BuildSpellBucketList(self)
	local allUnlocked, spells, _, talentTier = GetSpellsForCharacterUpgradeTier(self.level);

	self.unlockList = {};
	if (not allUnlocked) then
		if (spells) then
			for i = 1, #spells do
				local name, _, icon = GetSpellInfo(spells[i]);
				self.unlockList[#self.unlockList+1] = { entryType = "bucketspell", text = name, icon = icon };
			end
		else
			for i = 1, NUM_TALENT_COLUMNS do
				local _, name, icon = GetTalentInfo(talentTier, i, GetActiveSpecGroup());
				self.unlockList[#self.unlockList+1] = { entryType = "bucketspell", text = name, icon = icon };
			end
		end
	end

	self.currSpell = 1;
end

function LevelUpDisplay_BuildPetList(self)
	local name, icon = "","";
	self.unlockList = {};

	-- TODO: Pet Spells
	
	self.currSpell = 1;
end

function LevelUpDisplay_BuildBattlePetList(self)
	self.unlockList = {};
	
	-- TODO: Battle Pet spell slots & spells
	
	self.currSpell = 1;
end

function LevelUpDisplay_BuildEmptyList(self)
	self.unlockList = {};
	self.currSpell = 1;
end

function LevelUpDisplay_BuildGuildList(self)
	self.unlockList = {};
	
	for i=1, GetNumGuildPerks() do
		local name, spellID, iconTexture, level = GetGuildPerkInfo(i);
		if ( level == self.level ) then
			tinsert(self.unlockList, { text = name, subText = GUILD_LEVEL_UP_PERK, icon = iconTexture, subIcon = SUBICON_TEXCOOR_LOCK,
												link = GUILD_LEVEL_UP_PERK2.." "..GetSpellLink(spellID)
											});
		end
	end
	
	self.currSpell = 1;
end

function LevelUpDisplay_BuildGarrisonAbilityList(self)
	self.unlockList = {};

	local faction = UnitFactionGroup("player");
	local spellID = GARRISON_ABILITY_HACKS[self.buildingID][faction];
	local abilityText = GARRISON_ABILITY_HACKS[self.buildingID].Subtext;
	local name, _, texture = GetSpellInfo(spellID);
	tinsert(self.unlockList, { text = name, subText = abilityText, icon = texture, subIcon = SUBICON_TEXCOOR_BOOK, link = LEVEL_UP_ABILITY2.." "..GetSpellLink(spellID)});

	self.currSpell = 1;
end

function LevelUpDisplay_BuildPetBattleWinnerList(self)
	self.unlockList = {};
	self.winnerString = PET_BATTLE_RESULT_LOSE;
	if(C_PetBattles.IsWildBattle()) then
		self.winnerSoundKitID = 34090; --UI_PetBattle_PVE_Defeat
	elseif(C_PetBattles.IsPlayerNPC(LE_BATTLE_PET_ENEMY)) then
		self.winnerSoundKitID = 34094; --UI_PetBattle_Special_Defeat
	else
		self.winnerSoundKitID = 34092; --UI_PetBattle_PVP_Defeat
	end

	if ( self.winner == LE_BATTLE_PET_ALLY ) then
		self.winnerString = PET_BATTLE_RESULT_WIN;
		if(C_PetBattles.IsWildBattle()) then
			self.winnerSoundKitID = 34089; --UI_PetBattle_PVE_Victory
		elseif(C_PetBattles.IsPlayerNPC(LE_BATTLE_PET_ENEMY)) then
			self.winnerSoundKitID = 34093; --UI_PetBattle_Special_Victory
		else
			self.winnerSoundKitID = 34091; --UI_PetBattle_PVP_Victory
		end
	end;
	self.currSpell = 1;
end

function LevelUpDisplay_AddBattlePetTrapUpgradeEvent(self, trapLevel)
	if ( trapLevel < 1 or trapLevel > #LEVEL_UP_TRAP_LEVELS ) then
		return;
	end

	local name, icon, typeEnum = C_PetJournal.GetPetAbilityInfo(LEVEL_UP_TRAP_LEVELS[trapLevel]);

	if (name and self.unlockList) then
		table.insert(self.unlockList,
			{
			entryType = "spell",
			text = name,
			subText = PET_BATTLE_TRAP_UPGRADE,
			icon = icon,
			subIcon = nil
			});
	end
end

function LevelUpDisplay_AddBattlePetLevelUpEvent(self, activePlayer, activePetSlot, newLevel)
	if (activePlayer ~= LE_BATTLE_PET_ALLY) then
		return;
	end

	if (self.currSpell == 0) then
		self.type = TOAST_PET_BATTLE_LEVELUP;
		LevelUpDisplay_Show(self);
	end

	local petID = C_PetJournal.GetPetLoadOutInfo(activePetSlot);
	if (petID == nil) then
		return;
	end
	
	local speciesID, customName, petLevel, xp, maxXp, displayID, isFavorite, name, petIcon = C_PetJournal.GetPetInfoByPetID(petID);
	if (not speciesID) then
		return;
	end
	
	table.insert(self.unlockList, 
		{ 
		entryType = "petlevelup", 
		text = format(PET_LEVEL_UP_REACHED, customName or name), 
		subText = format(LEVEL_GAINED,newLevel), 
		icon = petIcon, 
		subIcon = SUBICON_TEXCOOR_ARROW,
		});
	local abilityID = PetBattleFrame_GetAbilityAtLevel(speciesID, newLevel);
	if (abilityID) then
		local abName, abIcon = C_PetJournal.GetPetAbilityInfo(abilityID);
		table.insert(self.unlockList,
			{
			entryType = "spell",
			text = abName,
			subText = LEVEL_UP_ABILITY,
			icon = abIcon,
			subIcon = nil,
			});
	end
end

function LevelUpDisplay_AddSpellBucketUnlockEvent(self, tierIndex)
	if (tierIndex == 0) then
		return;
	end

	if (self.currSpell == 0) then
		self.type = LEVEL_UP_TYPE_SPELL_BUCKET;
		self.tierIndex = tierIndex;
		LevelUpDisplay_Show(self);
		return;
	end

	table.insert(self.unlockList,
		{
		entryType = "spellbucket",
		tierIndex = tierIndex,
		});
end

function LevelUpDisplay_CreateOrAppendItem(self, createType, info)
	local unlockList = nil;
	if ( self.hideAnim:IsPlaying() or self.fastHideAnim:IsPlaying() ) then --If we're currently animating out
		self.queuedType = self.queuedType or createType;
		self.queuedItems = self.queuedItems or {};
		unlockList = self.queuedItems;
	elseif ( self.currSpell == 0 ) then --If we're currently hidden
		self.type = createType;
		LevelUpDisplay_Show(self);
		unlockList = self.unlockList;
	else --We're in the middle of showing something, just append it.
		unlockList = self.unlockList;
	end
	if ( unlockList ) then
		table.insert(unlockList, info)
	else
		GMError("No unlock list found.");
	end
end

function LevelUpDisplay_AddBattlePetCaptureEvent(self, fromPlayer, activePetSlot)
	if (fromPlayer ~= LE_BATTLE_PET_ENEMY) then
		return;
	end
	
	local petName = C_PetBattles.GetName(fromPlayer, activePetSlot);
	local petIcon = C_PetBattles.GetIcon(fromPlayer, activePetSlot);
	local quality = C_PetBattles.GetBreedQuality(fromPlayer, activePetSlot);
	
	local info = { 
		entryType = "petcapture", 
		text = BATTLE_PET_CAPTURED, 
		subText = petName, 
		icon = petIcon,
		quality = quality
	};
	LevelUpDisplay_CreateOrAppendItem(self, TOAST_PET_BATTLE_CAPTURE, info);
end

function LevelUpDisplay_AddBattlePetLootReward(self, typeIdentifier, itemLink, quantity)
	local info = nil;
	if ( typeIdentifier == "item" ) then
		local name, link, rarity, level, minLevel, itemType, itemSubType, itemStackCount, itemEquipLoc, itemTexture = GetItemInfo(itemLink);
		info = {
			entryType = "petbattleloot", 
			text = BATTLE_PET_LOOT_RECEIVED, 
			subText = name, --Item name
			icon = itemTexture, --Item icon
			quality = rarity, --Item quality
		};
	elseif ( typeIdentifier == "currency" ) then
		local name, quantity, icon, earnedThisWeek, weeklyMax, maxQuantity, discovered, rarity = GetCurrencyInfo(itemLink);
		info = {
			entryType = "petbattleloot",
			text = BATTLE_PET_LOOT_RECEIVED,
			subText = name,
			icon = icon,
			quality = rarity,
		};
	end

	if ( info ) then
		LevelUpDisplay_CreateOrAppendItem(self, TOAST_PET_BATTLE_LOOT, info);
	end
end

function LevelUpDisplay_Show(self)
	LevelUpDisplay_Start(self, nil);
end

function LevelUpDisplay_Start(self, beginUnlockList)
	if ( self:IsShown() ) then
		return;
	end

	if ( not IsPlayerInWorld() ) then
		-- this is pretty much the zoning-into-a-scenario case
		self:RegisterEvent("ZONE_CHANGED_NEW_AREA");
		return;
	end

	self:SetHeight(72);
	self:Show();
	ZoneTextFrame:Hide();	--LevelUpDisplay is more important than zoning text
	SubZoneTextFrame:Hide();
	
	local playAnim;
	if  self.currSpell == 0 then
		local unlockList = beginUnlockList;
		if ( not self.type ) then
			self.type = self.queuedType;
			unlockList = self.queuedItems;
			self.queuedType = nil;
			self.queuedItems = nil;
		end
		if ( self.type == LEVEL_UP_TYPE_SCENARIO ) then
			local name, currentStage, numStages, flags = C_Scenario.GetInfo();
			if ( currentStage > 0 and currentStage <= numStages ) then
				local stageName, stageDescription = C_Scenario.GetStepInfo();
				if( bit.band(flags, SCENARIO_FLAG_SUPRESS_STAGE_TEXT) == SCENARIO_FLAG_SUPRESS_STAGE_TEXT) then
					-- Bypass the Stage name portion...
					self.scenarioFrame.level:SetText(stageName);
					self.scenarioFrame.name:SetText("");
				else
					if ( currentStage == numStages ) then
						self.scenarioFrame.level:SetText(SCENARIO_STAGE_FINAL);
					else
						self.scenarioFrame.level:SetFormattedText(SCENARIO_STAGE, currentStage);
					end
					self.scenarioFrame.name:SetText(stageName);
				end
				self.scenarioFrame.description:SetText(stageDescription);
				LevelUpDisplay:SetPoint("TOP", 0, -250);
				playAnim = self.scenarioFrame.newStage;
			end
		elseif ( self.type == TOAST_CHALLENGE_MODE_RECORD ) then
			local medal = self.medal;
			if ( CHALLENGE_MEDAL_TEXTURES[medal] ) then
				self.challengeModeFrame.MedalEarned:SetText(_G["CHALLENGE_MODE_MEDALNAME"..medal]);
				self.challengeModeFrame.RecordTime:SetFormattedText(CHALLENGE_MODE_NEW_BEST, GetTimeStringFromSeconds(self.recordTime / 1000));
				self.challengeModeBits.MedalFlare:Show();
				self.challengeModeBits.MedalIcon:SetTexture(CHALLENGE_MEDAL_TEXTURES[medal]);
				self.challengeModeBits.MedalIcon:Show();
				self.challengeModeBits.BottomFiligree:Show();
			else
				-- no medal earned, still a record time for player
				self.challengeModeFrame.MedalEarned:SetText(CHALLENGE_MODE_NEW_RECORD);
				self.challengeModeFrame.RecordTime:SetText(GetTimeStringFromSeconds(self.recordTime / 1000));
				self.challengeModeBits.MedalFlare:Hide();
				self.challengeModeBits.MedalIcon:Hide();
				self.challengeModeBits.BottomFiligree:Hide();
			end
			PlaySound("UI_Challenges_NewRecord");
			LevelUpDisplay:SetPoint("TOP", 0, -190);
			playAnim = self.challengeModeFrame.challengeComplete;
		else
			LevelUpDisplay:SetPoint("TOP", 0, -190);
			playAnim = self.levelFrame.levelUp;
			self.levelFrame.reachedText:SetText("");
			self.levelFrame.levelText:SetText("");
			self.levelFrame.singleline:SetText("");
			self.levelFrame.blockText:SetText("");
			if ( self.type == LEVEL_UP_TYPE_CHARACTER ) then
				LevelUpDisplay_BuildCharacterList(self);
				self.levelFrame.reachedText:SetText(LEVEL_UP_YOU_REACHED)
				self.levelFrame.levelText:SetFormattedText(LEVEL_GAINED,self.level);
			elseif ( self.type == LEVEL_UP_TYPE_PET ) then
				LevelUpDisplay_BuildPetList(self);
				local petName = UnitName("pet");
				self.levelFrame.reachedText:SetFormattedText(PET_LEVEL_UP_REACHED, petName or "");
				self.levelFrame.levelText:SetFormattedText(LEVEL_GAINED,self.level);
			elseif ( self.type == LEVEL_UP_TYPE_GUILD ) then
				LevelUpDisplay_BuildGuildList(self);
				local guildName = GetGuildInfo("player");
				self.levelFrame.reachedText:SetFormattedText(GUILD_LEVEL_UP_YOU_REACHED, guildName);
				self.levelFrame.levelText:SetFormattedText(LEVEL_GAINED,self.level);
			elseif ( self.type == TOAST_PET_BATTLE_WINNER ) then
				LevelUpDisplay_BuildPetBattleWinnerList(self);
				self.levelFrame.singleline:SetText(self.winnerString);
				PlaySoundKitID(self.winnerSoundKitID);
				playAnim = self.levelFrame.fastReveal;
			elseif (self.type == TOAST_QUEST_BOSS_EMOTE ) then
				LevelUpDisplay_BuildEmptyList(self);
				self.levelFrame.blockText:SetText(self.bossText);
				if (self.sound and self.sound == true) then
					PlaySound("RaidBossEmoteWarning");
				end
				playAnim = self.levelFrame.fastReveal;
			elseif (self.type == TOAST_PET_BATTLE_CAPTURE ) then
				self.unlockList = unlockList or {};
				self.currSpell = 1;
				self.levelFrame.singleline:SetText(BATTLE_PET_CAPTURED);
				playAnim = self.levelFrame.fastReveal;
			elseif ( self.type == TOAST_PET_BATTLE_LOOT ) then
				self.unlockList = unlockList or {};
				self.currSpell = 1;
				self.levelFrame.singleline:SetText(BATTLE_PET_LOOT_RECEIVED);
				playAnim = self.levelFrame.fastReveal;
			elseif (self.type == TOAST_PET_BATTLE_LEVELUP ) then
				self.unlockList = unlockList or {};
				self.currSpell = 1;
				self.levelFrame.singleline:SetText(PLAYER_LEVEL_UP);
				playAnim = self.levelFrame.fastReveal;
			elseif ( self.type == LEVEL_UP_TYPE_SPELL_BUCKET ) then
				self.unlockList = unlockList or {};
				self.currSpell = 1;
				local tierIndex = self.tierIndex;
				if (tierIndex > 0) then
					local unlockAll, spells, tierName, talentTier = GetSpellsForCharacterUpgradeTier(tierIndex);
					if (unlockAll) then
						local icon = select(4, GetSpecializationInfo(GetSpecialization()));
						self.SpellBucketFrame.AllAbilitiesUnlocked.icon:SetTexture(icon);
						self.SpellBucketFrame.AllAbilitiesUnlocked.subIcon:SetTexCoord(unpack(SUBICON_TEXCOOR_BOOK));
						self.SpellBucketFrame.SpellBucketDisplay:Hide();
						self.SpellBucketFrame.AllAbilitiesUnlocked:Show();
						self:SetHeight(70);
					else
						local num, isTalents;
						if (spells) then
							num = #spells;
						else
							num = NUM_TALENT_COLUMNS;
							isTalents = true;
						end
						if (num > 5) then
							num = 5;
						end
						local index = #self.SpellBucketFrame.SpellBucketDisplay.BucketIcons + 1;
						local frameWidth, spacing = 56, 4;
						while (#self.SpellBucketFrame.SpellBucketDisplay.BucketIcons < num) do
							local frame = CreateFrame("Frame", nil, self.SpellBucketFrame.SpellBucketDisplay, "SpellBucketSpellTemplate");
							local prev = self.SpellBucketFrame.SpellBucketDisplay.BucketIcons[index - 1];
							frame:SetPoint("LEFT", prev, "RIGHT", spacing, 0);
							index = index + 1;
						end
						-- Figure out where to place the leftmost spell
						local frame = self.SpellBucketFrame.SpellBucketDisplay.BucketIcons[1];
						frame:ClearAllPoints();
						if (num % 2 == 1) then
							local x = (num - 1) / 2;
							frame:SetPoint("TOPLEFT", self.SpellBucketFrame.SpellBucketDisplay, "TOP", -((frameWidth / 2) + (frameWidth * x) + (spacing * x)), -42);
						else
							local x = num / 2;
							frame:SetPoint("TOPLEFT", self.SpellBucketFrame.SpellBucketDisplay, "TOP", -((frameWidth * x) + (spacing * (x - 1)) + (spacing / 2)), -42);
						end
						for i = 1, num do
							local name, icon, _;
							local spellframe = self.SpellBucketFrame.SpellBucketDisplay.BucketIcons[i];
							if (not isTalents) then
								local spellID = spells[i];
								name, _, icon = GetSpellInfo(spellID);
							else
								_, name, icon = GetTalentInfo(talentTier, i, GetActiveSpecGroup());
							end
							spellframe.name:SetText(name);
							spellframe.icon:SetTexture(icon);
							spellframe:Show();
						end
						for i = num+1, #self.SpellBucketFrame.SpellBucketDisplay.BucketIcons do
							self.SpellBucketFrame.SpellBucketDisplay.BucketIcons[i]:Hide();
						end
						self.SpellBucketFrame.SpellBucketDisplay.Name:SetText(tierName);
						self.SpellBucketFrame.AllAbilitiesUnlocked:Hide();
						self.SpellBucketFrame.SpellBucketDisplay:Show();
						self:SetHeight(112);
					end
					playAnim = self.SpellBucketFrame.bucketUnlocked;
				end
			elseif (self.type == TOAST_GARRISON_ABILITY ) then
				LevelUpDisplay_BuildGarrisonAbilityList(self);
			end
		end

		if ( playAnim ) then
			self.gLine:SetTexCoord(unpack(levelUpTexCoords[self.type].gLine));
			self.gLine2:SetTexCoord(unpack(levelUpTexCoords[self.type].gLine));
			if (levelUpTexCoords[self.type].tint) then
				self.gLine:SetVertexColor(unpack(levelUpTexCoords[self.type].tint));
				self.gLine2:SetVertexColor(unpack(levelUpTexCoords[self.type].tint));
			else
				self.gLine:SetVertexColor(1, 1, 1);
				self.gLine2:SetVertexColor(1, 1, 1);
			end
			if (levelUpTexCoords[self.type].textTint) then
				self.levelFrame.levelText:SetTextColor(unpack(levelUpTexCoords[self.type].textTint));
			else
				self.levelFrame.levelText:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b);
			end
			self.gLine.grow.anim1:SetStartDelay(levelUpTexCoords[self.type].gLineDelay);
			self.gLine2.grow.anim1:SetStartDelay(levelUpTexCoords[self.type].gLineDelay);
			self.blackBg.grow.anim1:SetStartDelay(levelUpTexCoords[self.type].gLineDelay);
			playAnim:Play();
			if (levelUpTexCoords[self.type].subIcon) then
				self.battlePetLevelFrame.subIcon:SetTexCoord(unpack(levelUpTexCoords[self.type].subIcon));
			end
		else
			self:Hide();
		end
	end
end


function LevelUpDisplay_AnimStep(self, fast)
	if self.currSpell > #self.unlockList then
		LevelUpDisplay_AnimOut(self, fast);
	else
		local spellInfo = self.unlockList[self.currSpell];
		self.currSpell = self.currSpell+1;

		self.spellFrame:Hide();
		self.DraenorTalentFrame:Hide();
		self.spellFrame.name:SetText("");
		self.spellFrame.flavorText:SetText("");
		self.spellFrame.middleName:SetText("");
		self.spellFrame.upperwhite:SetText("");
		self.spellFrame.bottomGiant:SetText("");
		self.spellFrame.subIcon:Hide();
		self.spellFrame.subIconRight:Hide();
		self.spellFrame.iconBorder:Hide();
		self.spellFrame.rarityUpperwhite:SetText("");
		self.spellFrame.rarityMiddleHuge:SetText("");
		self.spellFrame.rarityIcon:Hide();
		self.spellFrame.rarityValue:SetText("");
		self.spellFrame.rarityValue:Hide();
		
		if (not spellInfo.entryType or
			spellInfo.entryType == "spell" or
			spellInfo.entryType == "dungeon" or
			spellInfo.entryType == "heroicdungeon") then
			self.spellFrame.name:SetText(spellInfo.text);
			self.spellFrame.flavorText:SetText(spellInfo.subText);
			self.spellFrame.icon:Show();
			self.spellFrame.icon:SetTexture(spellInfo.icon);
			if (spellInfo.subIcon) then
				self.spellFrame.subIcon:Show();
				self.spellFrame.subIcon:SetTexCoord(unpack(spellInfo.subIcon));
			end
			self.spellFrame:Show();
			self.spellFrame.showAnim:Play();
		elseif (spellInfo.entryType == "petlevelup") then
			if (spellInfo.subIcon) then
				self.spellFrame.subIconRight:Show();
				self.spellFrame.subIconRight:SetTexCoord(unpack(spellInfo.subIcon));
			end
			self.spellFrame.icon:Show();
			self.spellFrame.icon:SetTexture(spellInfo.icon);
			self.spellFrame.upperwhite:SetText(spellInfo.text);
			self.spellFrame.bottomGiant:SetText(spellInfo.subText);
			self.spellFrame:Show();
			self.spellFrame.showAnim:Play();
		elseif (spellInfo.entryType == "petcapture") then
			self.spellFrame.icon:Show();
			self.spellFrame.icon:SetTexture(spellInfo.icon);
			self.spellFrame.rarityUpperwhite:SetText(spellInfo.text);
			self.spellFrame.rarityMiddleHuge:SetText(spellInfo.subText);
			if (spellInfo.quality) then
				self.spellFrame.iconBorder:Show();
				self.spellFrame.iconBorder:SetVertexColor(ITEM_QUALITY_COLORS[spellInfo.quality-1].r, ITEM_QUALITY_COLORS[spellInfo.quality-1].g, ITEM_QUALITY_COLORS[spellInfo.quality-1].b);
				self.spellFrame.rarityIcon:Show();
				self.spellFrame.rarityValue:SetText(_G["BATTLE_PET_BREED_QUALITY"..spellInfo.quality]);
				self.spellFrame.rarityValue:SetTextColor(ITEM_QUALITY_COLORS[spellInfo.quality-1].r, ITEM_QUALITY_COLORS[spellInfo.quality-1].g, ITEM_QUALITY_COLORS[spellInfo.quality-1].b);
				self.spellFrame.rarityValue:Show();
			end
			self.spellFrame:Show();
			self.spellFrame.showAnim:Play();
		elseif ( spellInfo.entryType == "petbattleloot" ) then
			self.spellFrame.icon:Show();
			self.spellFrame.flavorText:SetText(HIGHLIGHT_FONT_COLOR_CODE..spellInfo.text.."|r");
			self.spellFrame.icon:SetTexture(spellInfo.icon);
			local coloredText = ITEM_QUALITY_COLORS[spellInfo.quality].hex..spellInfo.subText.."|r";
			self.spellFrame.name:SetText(coloredText);
			self.spellFrame.iconBorder:Show();
			self.spellFrame.iconBorder:SetVertexColor(ITEM_QUALITY_COLORS[spellInfo.quality].r, ITEM_QUALITY_COLORS[spellInfo.quality].g, ITEM_QUALITY_COLORS[spellInfo.quality].b);
			self.spellFrame.subIconRight:Show();
			self.spellFrame.subIconRight:SetTexCoord(0.719, 0.779, 0.117, 0.178)
			self.spellFrame:Show();
			self.spellFrame.showAnim:Play();
		elseif ( spellInfo.entryType == "draenortalent" ) then
			LevelUpDisplayBlackBg:Hide();
			LevelUpDisplayGLine:Hide();
			LevelUpDisplayGLine2:Hide();
			self.DraenorTalentFrame.Icon:SetTexture(spellInfo.icon);
			self.DraenorTalentFrame.Icon2:SetTexture(spellInfo.icon);
			self.DraenorTalentFrame.spelltext:SetText(spellInfo.text);
			self.DraenorTalentFrame.descriptiontext:SetText(spellInfo.description);
			self.DraenorTalentFrame:Show();
			self.DraenorTalentFrame.showAnim:Play();
		elseif ( spellInfo.entryType == "spellbucket" ) then
			local tierIndex = spellInfo.tierIndex;
			if (tierIndex > 0) then
				local unlockAll, spells, tierName, talentTier = GetSpellsForCharacterUpgradeTier(tierIndex);
				if (unlockAll) then
					local icon = select(4, GetSpecializationInfo(GetSpecialization()));
					self.SpellBucketFrame.AllAbilitiesUnlocked.icon:SetTexture(icon);
					self.SpellBucketFrame.AllAbilitiesUnlocked.subIcon:SetTexCoord(unpack(SUBICON_TEXCOOR_BOOK));
					self.SpellBucketFrame.SpellBucketDisplay:Hide();
					self.SpellBucketFrame.AllAbilitiesUnlocked:Show();
					self:SetHeight(70);
				else
					local num, isTalents;
					if (spells) then
						num = #spells;
					else
						num = NUM_TALENT_COLUMNS;
						isTalents = true;
					end
					if (num > 5) then
						num = 5;
					end
					local index = #self.SpellBucketFrame.SpellBucketDisplay.BucketIcons + 1;
					local frameWidth, spacing = 56, 4;
					while (#self.SpellBucketFrame.SpellBucketDisplay.BucketIcons < num) do
						local frame = CreateFrame("Frame", nil, self.SpellBucketFrame.SpellBucketDisplay, "SpellBucketSpellTemplate");
						local prev = self.SpellBucketFrame.SpellBucketDisplay.BucketIcons[index - 1];
						frame:SetPoint("LEFT", prev, "RIGHT", spacing, 0);
						index = index + 1;
					end
					-- Figure out where to place the leftmost spell
					local frame = self.SpellBucketFrame.SpellBucketDisplay.BucketIcons[1];
					frame:ClearAllPoints();
					if (num % 2 == 1) then
						local x = (num - 1) / 2;
						frame:SetPoint("TOPLEFT", self.SpellBucketFrame.SpellBucketDisplay, "TOP", -((frameWidth / 2) + (frameWidth * x) + (spacing * x)), -42);
					else
						local x = num / 2;
						frame:SetPoint("TOPLEFT", self.SpellBucketFrame.SpellBucketDisplay, "TOP", -((frameWidth * x) + (spacing * (x - 1)) + (spacing / 2)), -42);
					end
					for i = 1, num do
						local name, icon, _;
						local spellframe = self.SpellBucketFrame.SpellBucketDisplay.BucketIcons[i];
						if (not isTalents) then
							local spellID = spells[i];
							name, _, icon = GetSpellInfo(spellID);
						else
							_, name, icon = GetTalentInfo(talentTier, i, GetActiveSpecGroup());
						end
						spellframe.name:SetText(name);
						spellframe.icon:SetTexture(icon);
						spellframe:Show();
					end
					for i = num+1, #self.SpellBucketFrame.SpellBucketDisplay.BucketIcons do
						self.SpellBucketFrame.SpellBucketDisplay.BucketIcons[i]:Hide();
					end
					self.SpellBucketFrame.SpellBucketDisplay.Name:SetText(tierName);
					self.SpellBucketFrame.AllAbilitiesUnlocked:Hide();
					self:SetHeight(112);
				end
				self.SpellBucketFrame:Show();
				self.SpellBucketFrame.bucketUnlocked:Play();
			else
				LevelUpDisplay_AnimStep(self, fast);
			end
		end
	end
end

function LevelUpDisplay_AnimOut(self, fast)
	self = self or LevelUpDisplay;
	self.currSpell = 0;
	self.type = nil;
	if (fast) then
		self.fastHideAnim:Play();
	else
		self.hideAnim:Play();
	end
end

function LevelUpDisplay_AnimOutFinished(anim)
	local parent = LevelUpDisplay;
	if ( parent.extraFrame ) then
		parent.extraFrame:Hide();
		parent.extraFrame = nil;
	end
	parent:Hide();
	--In case we had to queue something up while fading
	if ( parent.queuedType ) then
		LevelUpDisplay_Show(parent);
	end
end

--Side display Functions

function LevelUpDisplay_ShowSideDisplay(level, levelUpType, arg1)
	if LevelUpDisplaySide.level and LevelUpDisplaySide.level == level and LevelUpDisplaySide.type == levelUpType and LevelUpDisplaySide.arg1 == arg1 then
		if LevelUpDisplaySide:IsVisible() then		
			LevelUpDisplaySide:Hide();	
		else	
			LevelUpDisplaySide:Show();
		end
	else
		LevelUpDisplaySide.level = level;
		LevelUpDisplaySide.type = levelUpType;
		LevelUpDisplaySide.arg1 = arg1;
		LevelUpDisplaySide:Hide();
		LevelUpDisplaySide:Show();
	end
end


function LevelUpDisplaySide_OnShow(self)
	self.abilitiesUnlocked:Hide();
	self.spellBucketName:Hide();
	self.reachedText:Show();
	self.levelText:Show();
	if ( self.type == LEVEL_UP_TYPE_CHARACTER ) then
		LevelUpDisplay_BuildCharacterList(self);
		self.reachedText:SetText(LEVEL_UP_YOU_REACHED);
		self.levelText:SetFormattedText(LEVEL_GAINED,self.level);
	elseif ( self.type == LEVEL_UP_TYPE_PET ) then
		LevelUpDisplay_BuildPetList(self);
		local petName = self.arg1;
		self.reachedText:SetFormattedText(PET_LEVEL_UP_REACHED, petName);
		self.levelText:SetFormattedText(LEVEL_GAINED,self.level);
	elseif ( self.type == LEVEL_UP_TYPE_GUILD ) then
		LevelUpDisplay_BuildGuildList(self);
		local guildName = GetGuildInfo("player");
		self.reachedText:SetFormattedText(GUILD_LEVEL_UP_YOU_REACHED, guildName);
		self.levelText:SetFormattedText(LEVEL_GAINED,self.level);
	elseif ( self.type == LEVEL_UP_TYPE_SPELL_BUCKET ) then
		LevelUpDisplay_BuildSpellBucketList(self);
		self.reachedText:Hide();
		self.levelText:Hide();
		local _, _, name = GetSpellsForCharacterUpgradeTier(self.level);
		self.spellBucketName:SetText(name);
		self.abilitiesUnlocked:Show();
		self.spellBucketName:Show();
	end
	self.goldBG:SetTexCoord(unpack(levelUpTexCoords[self.type].goldBG));
	self.dot:SetTexCoord(unpack(levelUpTexCoords[self.type].dot));
	
	if (levelUpTexCoords[self.type].tint) then
		self.goldBG:SetVertexColor(unpack(levelUpTexCoords[self.type].tint));
		self.dot:SetVertexColor(unpack(levelUpTexCoords[self.type].tint));
	else
		self.goldBG:SetVertexColor(1, 1, 1);
		self.dot:SetVertexColor(1, 1, 1);
	end
	
	if (levelUpTexCoords[self.type].textTint) then
		self.levelText:SetTextColor(unpack(levelUpTexCoords[self.type].textTint));
	else
		self.levelText:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b);
	end
	
	local i = 1;
	local displayFrame = _G["LevelUpDisplaySideUnlockFrame1"];
	while i <=  #self.unlockList do	
		if not displayFrame then -- make frames as needed
			displayFrame = CreateFrame("FRAME", "LevelUpDisplaySideUnlockFrame"..i, LevelUpDisplaySide, "LevelUpSkillTemplate");
			displayFrame:SetPoint("TOP",  _G["LevelUpDisplaySideUnlockFrame"..(i-1)], "BOTTOM", 0, -1);
			displayFrame:SetAlpha(0.0);
		end
		i = i+1;		
		displayFrame = _G["LevelUpDisplaySideUnlockFrame"..i];
	end
	self:SetHeight(65);
	self.fadeIn:Play();
end

function LevelUpDisplaySide_OnHide(self)
	local displayFrame = _G["LevelUpDisplaySideUnlockFrame1"];
	local i = 1;
	while displayFrame do 	
		if displayFrame.sideAnimIn:IsPlaying() then
			displayFrame.sideAnimIn:Stop();
		end				
		displayFrame:SetAlpha(0.0);
		i = i+1;
		displayFrame = _G["LevelUpDisplaySideUnlockFrame"..i];
	end	
end


function LevelUpDisplaySide_AnimStep(self)

	if self.currSpell > 1 then
		_G["LevelUpDisplaySideUnlockFrame"..(self.currSpell-1)]:SetAlpha(1.0);
	end	

	if self.currSpell <= #self.unlockList then
		local spellInfo = self.unlockList[self.currSpell];
		local displayFrame = _G["LevelUpDisplaySideUnlockFrame"..self.currSpell];
		if (spellInfo.entryType and spellInfo.entryType == "bucketspell") then
			displayFrame.name:SetText("");
			displayFrame.flavorText:SetText("");
			displayFrame.middleName:SetText(spellInfo.text);
			displayFrame.icon:SetTexture(spellInfo.icon);
			displayFrame.subIcon:Hide();
		else
			displayFrame.name:SetText(spellInfo.text);
			displayFrame.flavorText:SetText(spellInfo.subText);
			displayFrame.icon:SetTexture(spellInfo.icon);
			displayFrame.subIcon:SetTexCoord(unpack(spellInfo.subIcon));
			displayFrame.subIcon:Show();
		end
		displayFrame.subIconRight:Hide();
		displayFrame.sideAnimIn:Play();
		self.currSpell = self.currSpell+1;
		self:SetHeight(self:GetHeight()+45);
	end
end

function LevelUpDisplaySide_Remove()
	LevelUpDisplaySide.fadeOut:Play();
end


-- Chat print function 
function LevelUpDisplay_ChatPrint(self, level, levelUpType, ...)
	local info;
	local chatLevelUP = {level = level, type = levelUpType};
	local levelstring;
	if ( levelUpType == LEVEL_UP_TYPE_CHARACTER ) then
		LevelUpDisplay_BuildCharacterList(chatLevelUP);
		levelstring = format(LEVEL_UP, level, level);
		info = ChatTypeInfo["SYSTEM"];
	elseif ( levelUpType == LEVEL_UP_TYPE_PET ) then
		LevelUpDisplay_BuildPetList(chatLevelUP);
		local petName = UnitName("pet");
		if (petName) then
			levelstring = format(PET_LEVEL_UP, petName, level, petName, level);
		else
			levelstring = "";
		end
		info = ChatTypeInfo["SYSTEM"];
	elseif ( levelUpType == LEVEL_UP_TYPE_GUILD ) then
		LevelUpDisplay_BuildGuildList(chatLevelUP);
		local guildName = GetGuildInfo("player");
		levelstring = format(GUILD_LEVEL_UP, guildName, level, level);
		info = ChatTypeInfo["GUILD"];
	elseif ( levelUpType == LEVEL_UP_TYPE_SPELL_BUCKET ) then
		local allUnlocked, _, name = GetSpellsForCharacterUpgradeTier(level);
		if (allUnlocked) then
			local class = UnitClass("player");
			levelstring = format(SPELL_BUCKET_ALL_ABILITIES_UNLOCKED_MESSAGE, class);
		else
			LevelUpDisplay_BuildSpellBucketList(chatLevelUP);
			levelstring = format(SPELL_BUCKET_LEVEL_UP, level, name or "");
		end
		info = ChatTypeInfo["SYSTEM"];
	end
	self:AddMessage(levelstring, info.r, info.g, info.b, info.id);
	if (chatLevelUP.unlockList) then
		for _,skill in pairs(chatLevelUP.unlockList) do
			if skill.entryType == "heroicdungeon" then
				local name, link = EJ_GetTierInfo(skill.tier);
				self:AddMessage(LEVEL_UP_HEROIC2..link, info.r, info.g, info.b, info.id);
			elseif skill.entryType ~= "spell" and skill.entryType ~= "bucketspell" then
				self:AddMessage(skill.link, info.r, info.g, info.b, info.id);
			end
		end
	end
end

function LevelUpDraenorTalent_OnLoad(self)
	self.beginLeft = 0;
	self.beginRight = 0.43359375;

	self.left = self.beginLeft;
	self.right = self.beginRight;

	self.beginWidth = 222;

	self.leftWidth = self.beginWidth;
	self.rightWidth = 0;

	self.Icon2:SetVertexColor(1,1,1);
	self.book2:SetVertexColor(1,1,1);
end

function LevelUpDraenorTalent_SpinnerUpdate(self, elapsed)
	self = self:GetParent():GetParent();
	-- Shifts 512 pixels every .57 seconds, 898.246 pixels every second
	self.shift = 898.246 * elapsed;
	self.move = self.shift / 512;

	if (not self.reset) then
		self.left = self.left + self.move;
		self.right = self.right + self.move;

		if (self.right > 1) then
			local diff = self.right - 1;
			self.right = 1;
			self.left = self.left + diff;

			self.reset = true;
		end
		self.SpinningPlateLeft:SetTexCoord(self.left, self.right, 0, 1);
	else
		self.rightWidth = self.rightWidth + self.shift;
		self.leftWidth = self.leftWidth - self.shift;

		self.SpinningPlateLeft:SetWidth(self.leftWidth);
		self.SpinningPlateRight:SetWidth(self.rightWidth);

		if (self.leftWidth <= 0) then
			self.SpinningPlateRight:Hide();
			self.SpinningPlateLeft:SetWidth(self.beginWidth);
			self.SpinningPlateLeft:SetTexCoord(self.beginLeft, self.beginRight, 0, 1);

			self.leftWidth = self.beginWidth;
			self.rightWidth = 0;

			self.left = self.beginLeft;
			self.right = self.beginRight;

			self.reset = false;
		else
			self.SpinningPlateRight:Show();
			self.left = self.left + self.move;

			self.SpinningPlateLeft:SetTexCoord(self.left, self.right, 0, 1);

			local tLeft = 0; -- always 0, this is the reset one
			local tRight = self.rightWidth / 512;
			self.SpinningPlateRight:SetTexCoord(tLeft, tRight, 0, 1);
		end
	end
end