----------------------------------------------------------------------------
-- $Id: Sea.wow.spellbook.lua 3858 2006-08-03 09:25:19Z karlkfi $
--
-- WoW Spellbook cache
----------------------------------------------------------------------------

local SEA_SPELLBOOK_VERSION = 1.8;
local loadThisEmbeddedInstance;
SEA_SPELLBOOK_DEBUG = nil;
------------------------------------------------------------------------------
--[[ Embedded Sub-Library Load Algorithm ]]--
------------------------------------------------------------------------------

if (not Sea) then
	Sea = {};
	Sea.versions = {};
	Sea.versions.SeaSpellbook = SEA_SPELLBOOK_VERSION;
	loadThisEmbeddedInstance = true;
	Sea.wow = {};
	Sea.wow.spellbook = {};
else
	if (not Sea.versions) then
		Sea.versions = {};
	end
	if (not Sea.versions.SeaSpellbook) or (Sea.versions.SeaSpellbook < SEA_SPELLBOOK_VERSION) then
		Sea.versions.SeaSpellbook = SEA_SPELLBOOK_VERSION;
		loadThisEmbeddedInstance = true;
	end
	if (not Sea.wow) then
		Sea.wow = {};
	end
	if (not Sea.wow.spellbook) then
		Sea.wow.spellbook = {};
	end
end

if (loadThisEmbeddedInstance) then
	loadThisEmbeddedInstance = nil;

	
	--
	-- Setup all our variables and tables
	--
	
	Sea.wow.spellbook = {
		firstRun = true,
	
		scholars = {},
		[BOOKTYPE_SPELL] = {},
		[BOOKTYPE_PET] = {},
		textures = { [BOOKTYPE_SPELL] = {}, [BOOKTYPE_PET] = {}, },
	}
	
	local SeaSpellbook_Compare, SeaSpellbook_FindPattern
	
	--
	-- Create a new frame if none exist
	--
	if not Sea.wow.spellbook.FRAME then
		Sea.wow.spellbook.FRAME = CreateFrame("Frame", "SeaSpellbookFrame")
	end
	
	
	--
	-- Create tooltip frame
	--
	if not Sea.wow.spellbook.TOOLTIP then
		local tooltip = CreateFrame("GameTooltip", "SeaSpellbookTooltip", nil, "GameTooltipTemplate")
		tooltip:SetOwner(UIParent, "ANCHOR_NONE")
		Sea.wow.spellbook.TOOLTIP = tooltip
		--[[
		for i = 1, 30 do
			SeaSpellbookTooltip:CreateFontString("SeaSpellbookTooltipTextRight" .. i)
			SeaSpellbookTooltip:CreateFontString("SeaSpellbookTooltipTextLeft" .. i)
		end
		]]--
	end
	
	
	--
	-- OnEvent handler
	--
	-- We monitor a few events to get our data.
	Sea.wow.spellbook.OnEvent = function()
		Sea.wow.spellbook.dprint(SEA_SPELLBOOK_DEBUG, "Sea spellbook: ", event, " ", arg1)
	
		-- Pet spellbook update
		-- UNIT_PET - Call/Dismiss
		-- UNIT_PET_TRAINING_POINTS - Training pet
		if event == "UNIT_PET" and arg1 == "player" or
			event == "UNIT_PET_TRAINING_POINTS" then
	
			if HasPetSpells() then
				if GetTime() - Sea.wow.spellbook.petTimer > 3 then
					Sea.wow.spellbook[BOOKTYPE_PET] = {}
					SeaSpellbook[BOOKTYPE_PET] = Sea.wow.spellbook[BOOKTYPE_PET]
					Sea.wow.spellbook[BOOKTYPE_PET].petName = UnitName("pet")
					Sea.wow.spellbook.ReadSpellbook( BOOKTYPE_PET )
					Sea.wow.spellbook.petTimer = GetTime()
				end
			else
				Sea.wow.spellbook[BOOKTYPE_PET].petName = nil
			end
	
		-- When the spellbook change this event is fired
		elseif event == "LEARNED_SPELL_IN_TAB" then
			Sea.wow.spellbook.ReadSpellTab( BOOKTYPE_SPELL, arg1)
			Sea.wow.spellbook.CallScholars( BOOKTYPE_SPELL )
	
		-- Mana cost changes for some spells on level up
		-- Talents effects the spellbook
		elseif event == "PLAYER_LEVEL_UP" or 
			event == "CHARACTER_POINTS_CHANGED" and arg1 == -1 then
			Sea.wow.spellbook.ReadSpellbook( BOOKTYPE_SPELL )
	
		-- First event where we can always read the spellbook
		elseif event == "PLAYER_ENTERING_WORLD" then
			Sea.wow.spellbook.Pew()
	
		-- Handle Blizzards Zoning nonsense
		elseif event == "PLAYER_LEAVING_WORLD" then
			this:UnregisterEvent("UNIT_PET")
	
		-- Initialization
		elseif event == "VARIABLES_LOADED" then
			Sea.wow.spellbook.petTimer = GetTime()
	
			local _, eClass = UnitClass("player")
			if eClass == "WARLOCK" or eClass == "HUNTER" then
				Sea.wow.spellbook.petClass = true
			end
	
			this:RegisterEvent("PLAYER_ENTERING_WORLD")
		end
	end
	
	
	--
	-- Register our OnEvent handler with the frame.
	--
	Sea.wow.spellbook.FRAME:SetScript("OnEvent", Sea.wow.spellbook.OnEvent)
	
	
	--
	-- Setup our initialization event
	--
	Sea.wow.spellbook.FRAME:RegisterEvent("VARIABLES_LOADED")
	
	
	--
	-- Pew()
	--
	-- PLAYER_ENTERING_WORLD
	Sea.wow.spellbook.Pew = function()
		Sea.wow.spellbook.pew = true
	
		-- If no one has registered with us, we don't do any work
		if  #Sea.wow.spellbook.scholars > 0 then
			-- Only do the setup once
			if Sea.wow.spellbook.firstRun then
				Sea.wow.spellbook.firstRun = false
	
				Sea.wow.spellbook.ReadSpellbook( BOOKTYPE_SPELL )
	
				if Sea.wow.spellbook.petClass and HasPetSpells() then
					Sea.wow.spellbook[BOOKTYPE_PET].petName = UnitName("pet")
					Sea.wow.spellbook.ReadSpellbook( BOOKTYPE_PET )
					Sea.wow.spellbook.petTimer = GetTime()
				end
	
				-- Register our events now we are ready to handle them
				this:RegisterEvent("PLAYER_LEVEL_UP")
				this:RegisterEvent("LEARNED_SPELL_IN_TAB")
				this:RegisterEvent("CHARACTER_POINTS_CHANGED")
	
				if Sea.wow.spellbook.petClass then
					this:RegisterEvent("UNIT_PET_TRAINING_POINTS")
				else
					this:UnregisterEvent("PLAYER_ENTERING_WORLD")
				end
			end
	
			-- Zone event overload fix
			if Sea.wow.spellbook.petClass then
				this:RegisterEvent("UNIT_PET")
	
				if Sea.wow.spellbook[BOOKTYPE_PET].petName then
					Sea.wow.spellbook.petTimer = GetTime()
				end
			end
	
		end
	
	end
	
	
	--
	-- RegisterScholar( { scholar } )
	--	scholar - table
	--		{
	--			id		- Unique id for the scholar
	--			callback	- callback function (Optional)
	--				callback( bookType )
	--
	--					bookType - 1 spellbook, 2 petbook, 3 both
	--
	--			feedback	- table (Optional - Required if callback is present)
	--				{
	--					spell = true,	- Set this to get called when the spellbook updates
	--					pet = true,	- And for petbook updates.
	--				}
	--
	--			description	- description string (Optional)
	--		}
	--
	-- Register a scholar with the specified id, that will be informed when the spellbook change
	Sea.wow.spellbook.RegisterScholar = function( scholar )
		--[[ Are we ready to rumble!
		if not  Sea.wow.spellbook.variablesLoaded then
			Sea.wow.spellbook.print("SeaSpellbook: ", this:GetName(), " called us before we where initialized")
			return false
		end
		]]--
	
		-- Check that scholar seems correct
		if not Sea.wow.spellbook.VerifyScholar( scholar ) then
			return false
		end
	
		local scholars = Sea.wow.spellbook.scholars
	
		-- Avoid that the same function is registered multiple times
		if #scholars > 0 then
			for i=1, #scholars do
				if scholars[i].id == scholar.id then
					Sea.wow.spellbook.print("SeaSpellbook: ", this:GetName(), " tried to register an already registered scholar.id")
					return false
				end
			end
		end
	
		tinsert( scholars, scholar )
		
		-- Call the newly created Scholar
		if Sea.wow.spellbook.pew and Sea.wow.spellbook.firstRun then
			Sea.wow.spellbook.Pew()
		elseif Sea.wow.spellbook.pew and not Sea.wow.spellbook.firstRun then
			local success, result = pcall( scholar.callback, bookType )
			if not success then
				message( result )
				Sea.wow.spellbook.print( "SeaSpellbook: Failed calling ", scholar.id )
				tremove(scholars, #scholars )
	
				return false
			end
		end
	
		return true
	end
	
	
	--
	-- UnregisterScholar( id )
	--
	--
	-- Remove a registered Scholar
	Sea.wow.spellbook.UnregisterScholar = function( id )
		local scholars = Sea.wow.spellbook.scholars
	
		if #scholars > 0 then
			for i=1, #scholars do
				if scholars[i].id == id then
					tremove( scholars, i )
					return true
				end
			end
		end
	
		Sea.wow.spellbook.print("SeaSpellbook: ", this:GetName(), " tried to unregister unknown scholar id.")
		return false
	end
	
	
	--
	-- CallScholars( bookType )
	--
	-- Call the registered Scholars
	Sea.wow.spellbook.CallScholars = function( bookType )
		local scholars = Sea.wow.spellbook.scholars
	
		for key, value in pairs(scholars) do
			if value.callback and value.feedback[bookType] then
				local success, result = pcall( value.callback, bookType )
				if not success then
					message( result )
					Sea.wow.spellbook.print( "SeaSpellbook: Failed calling ", value.id )
					tremove(scholars, key)
				end
			end
		end
	end
	
	
	--
	-- VerifyScholar( scholar )
	--
	-- Verify's that a correct scholar table has been submitted to us
	Sea.wow.spellbook.VerifyScholar = function( scholar )
		if type(scholar) ~= "table" then
			Sea.wow.spellbook.print("SeaSpellbook: ", this:GetName(), " called us with an incorrect scholar.")
			return false
		end
	
		if not scholar.id then
			Sea.wow.spellbook.print("SeaSpellbook: ", this:GetName(), " called us with missing scholar.id.")
			return false
		end
	
		if scholar.callback and type(scholar.callback) ~= "function" then
			Sea.wow.spellbook.print("SeaSpellbook: ", this:GetName(), " called us with incorrect scholar.callback.")
			return false
		end
	
		if scholar.callback and not scholar.feedback then
			Sea.wow.spellbook.print("SeaSpellbook: ", this:GetName(), " called us with missing scholar.feedback.")
			return false
		end
	
		if scholar.feedback and type(scholar.feedback) ~= "table" then
			Sea.wow.spellbook.print("SeaSpellbook: ", this:GetName(), " called us with incorrect scholar.feedback.")
			return false
		end
	
		if scholar.feedback and not scholar.feedback.pet and not scholar.feedback.spell then
			Sea.wow.spellbook.print("SeaSpellbook: ", this:GetName(), " called us with no known feedback selection.")
			return false
		end

		if scholar.description and type(scholar.description) ~= "string" then
			Sea.wow.spellbook.print("SeaSpellbook: ", this:GetName(), " called us with incorrect scholar.description.")
			return false
		end
	
		return true
	end
	
	
	--
	-- ReadSpellbook( spellTab )
	--	No arguments and it reads all tabs
	--	spellTab # - To only update that tab
	--
	-- Function to decide how much of the spellbook we should read.
	Sea.wow.spellbook.ReadSpellbook = function( bookType, spellTab )
		if bookType == BOOKTYPE_SPELL then
			for i=1, GetNumSpellTabs() do
				Sea.wow.spellbook.ReadSpellTab( bookType, i )
			end
		else
			Sea.wow.spellbook.ReadSpellTab(bookType)
		end
	
		Sea.wow.spellbook.CallScholars( bookType )
	end
	
	
	--
	-- ReadSpellTab( bookType, tabIndex )
	--	bookType = "spell" or "pet"
	--	tabIndex = Spellbook tab #
	--
	-- Reads a tab in the spellbook into our table
	Sea.wow.spellbook.ReadSpellTab = function( bookType, tabIndex, forceTooltip )
		local startIndex = 1
		local i = 1
		local maxIndex, _
	
		-- Shortcuts for easy access to our tables
		local spells	= Sea.wow.spellbook[bookType]
		local textures	= Sea.wow.spellbook.textures[bookType]
	
		if bookType == BOOKTYPE_SPELL then
			-- Get the spell index we should start with.
			while i < tabIndex do
				local _, _, _, numSpells = GetSpellTabInfo( i )
				startIndex = startIndex + numSpells
				i = i + 1
			end
	
			-- Get the number of spells we should read
			local _, _, _, numSpells = GetSpellTabInfo( tabIndex )
	
			-- Since we calculated up to this point already, we reuse
			-- startIndex, but has to subtract 1.
			maxIndex = ( startIndex - 1 ) + numSpells
		else
			maxIndex, _ = HasPetSpells()
		end
	
		-- Do the work of reading the choosen list of spells
		for index=startIndex, maxIndex  do
			local spellName, spellRank = GetSpellName( index, bookType )
			local spellTexture = GetSpellTexture( index, bookType )
	
			-- This code removes anything that isn't numbers, so even while spellRank
			-- isn't localized, we should still always parse it correctly.
			local rank, _ = gsub( spellRank, "(%D+)", "", 1 )
			rank = tonumber( rank )
	
			-- Unranked?
			if not rank then
				rank = 0
			end
	
			-- Main database of spells initialization
			if not spells[spellName] then
				spells[spellName] = {}
			end
	
			if not spells[spellName][rank] then
				spells[spellName][rank] = {}
				spells[spellName][rank].ID = index
	
			elseif 	spells[spellName][rank].ID ~= index then
				spells[spellName][rank].ID = index
			end
	
			spells[spellName].spellTexture = spellTexture
	
			-- Pet spells AutoCast status
			if bookType == BOOKTYPE_PET then
				local autoCast, _ = GetSpellAutocast( index, BOOKTYPE_PET )
				if autoCast then
					spells[spellName].autoCast = true
				end
			end
	
			-- texture database for searching quicker
			local found = false
			if not textures[spellTexture] then
				textures[spellTexture] = {}
			else
				-- No need to add double textures for multi rank spells
				for i=1, #textures[spellTexture] do
					if textures[spellTexture][i] == spellName then
						found = true
						break
					end
				end
			end
			if not found then
				tinsert( textures[spellTexture], spellName )
			end
	
			-- The very slow tooltip scanning
			Sea.wow.spellbook.GetSpellDetails( index, bookType, spells[spellName][rank] )
			spells[spellName][rank].rank = spellRank
	
			if rank ~= 0 then
				spells[spellName][0] = spells[spellName][rank]
			end
		end
	end
	
	
	--
	-- GetSpellDetails( index, bookType, spellType )
	--	index		= Spell Index
	--	bookType	= "spell" or "pet"
	--	spellTable	= Where we store the data
	--
	--	Returns a table: {
	--		ID		- SpellID for the spell in the spellbook
	--		castTime	- positive secs of cast time
	--				-  0 Channeled
	--				- -1 Instant Cast
	--				- -2 Instant
	--				- -3 Next melee / Next Ranged
	--		crit		- x.x% crit chance
	--		manaCost	- Mana cost
	--		energyCost	- Energy cost
	--		rageCost	- Rage cost
	--		minRange	- Casting min range to target
	--		maxRange	- Casting max range to target
	--		cooldown	- cooldown between casts in seconds
	--	These variables aren't localized
	--		requires	- What is required before the spell can be cast?
	--		tools		- Tools required to cast the spell
	--		reagents	- Reagents required to cast the spell
	--		description	- Description
	--
	-- Read the tooltip to get detailed information about a spell
	Sea.wow.spellbook.GetSpellDetails = function( index, bookType, spellTable )
		spellTable.ID = index
	
		-- Clear the tooltip so we don't have old data
		SeaSpellbookTooltip:ClearLines()
	
		-- ClearLines() doesn't clear the Right
		SeaSpellbookTooltipTextRight1:SetText()
		SeaSpellbookTooltipTextRight2:SetText()
		SeaSpellbookTooltipTextRight3:SetText()
		SeaSpellbookTooltipTextRight4:SetText()
		SeaSpellbookTooltipTextRight5:SetText()
	
		-- Set the tooltip with a spell
		SeaSpellbookTooltip:SetSpell( index, bookType )
	
		local tooltipText, temp
		-- L1 name
		-- Ignored
	
		for runSide = 1, 2 do
			if runSide == 1 then
				tooltipSide = "Left"
			else
				tooltipSide = "Right"
			end
	
			for runLevel = 2, 6 do
				tooltipText = getglobal("SeaSpellbookTooltipText" .. tooltipSide .. runLevel):GetText()
	
				if tooltipText == nil then
				-- Do nothing
	
				--	Instant
				elseif runLevel >= 2 and runLevel <= 3 and runSide == 1 and
					SEASPELLBOOK_INSTANT.func( tooltipText, SEASPELLBOOK_INSTANT.string ) then
					spellTable.castTime = -2
	
				--	Instant cast
				elseif runLevel == 3 and runSide == 1 and
					SEASPELLBOOK_INSTANTCAST.func( tooltipText, SEASPELLBOOK_INSTANTCAST.string ) then
	
					spellTable.castTime = -1
	
				--	Channeled
				elseif runLevel == 3 and runSide == 1 and
					SEASPELLBOOK_CHANNELED.func( tooltipText, SEASPELLBOOK_CHANNELED.string ) then
	
					spellTable.castTime = 0
	
				--	Next melee
				elseif runLevel == 3 and runSide == 1 and
					SEASPELLBOOK_NEXTMELEE.func( tooltipText, SEASPELLBOOK_NEXTMELEE.string ) then
	
					spellTable.castTime = -3
	
				--	Attack Speed
				elseif runLevel == 3 and runSide == 1 and
					SEASPELLBOOK_NEXTRANGED.func( tooltipText, SEASPELLBOOK_NEXTRANGED.string ) then
	
					spellTable.castTime = -3
	
				--	#.#% chance to crit
				elseif runLevel == 2 and runSide == 1 and
					SEASPELLBOOK_CRITCHANCE.func( tooltipText, SEASPELLBOOK_CRITCHANCE.string ) then
	
					temp, _ = gsub(tooltipText, SEASPELLBOOK_CRITCHANCE.string, "%1")
					spellTable.crit = tonumber( temp )
	
				--	#.#% chance to parry
				elseif runLevel == 3 and runSide == 1 and
					SEASPELLBOOK_PARRYCHANCE.func( tooltipText, SEASPELLBOOK_PARRYCHANCE.string ) then
	
					temp, _ = gsub(tooltipText, SEASPELLBOOK_PARRYCHANCE.string, "%1")
					spellTable.parry = tonumber( temp )
	
				--	#.#% chance to block
				elseif runLevel == 3 and runSide == 1 and
					SEASPELLBOOK_BLOCKCHANCE.func( tooltipText, SEASPELLBOOK_BLOCKCHANCE.string ) then
	
					temp, _ = gsub(tooltipText, SEASPELLBOOK_BLOCKCHANCE.string, "%1")
					spellTable.block = tonumber( temp )
	
				--	#.#% chance to dodge
				elseif runLevel == 2 and runSide == 1 and
					SEASPELLBOOK_DODGECHANCE.func( tooltipText, SEASPELLBOOK_DODGECHANCE.string ) then
	
					temp, _ = gsub(tooltipText, SEASPELLBOOK_DODGECHANCE.string, "%1")
					spellTable.dodge = tonumber( temp )
	
				--	# Mana
				elseif runLevel == 2 and runSide == 1 and
					SEASPELLBOOK_MANA.func(tooltipText, SEASPELLBOOK_MANA.string ) then
	
					temp, _ = gsub(tooltipText, SEASPELLBOOK_MANA.string, "%1")
					spellTable.manaCost = tonumber( temp )
	
				--	# Focus
				elseif runLevel == 2 and runSide == 1 and
					SEASPELLBOOK_FOCUS.func(tooltipText, SEASPELLBOOK_FOCUS.string ) then
	
					temp, _ = gsub(tooltipText, SEASPELLBOOK_FOCUS.string, "%1")
					spellTable.focusCost = tonumber( temp )
	
				--	Uses 100% mana
				elseif runLevel == 4 and runSide == 1 and
					SEASPELLBOOK_MANAALL.func(tooltipText, SEASPELLBOOK_MANAALL.string ) then
	
					spellTable.manaCost = -1
	
				--	# Energy
				elseif runLevel == 2 and runSide == 1 and
					SEASPELLBOOK_ENERGY.func(tooltipText, SEASPELLBOOK_ENERGY.string ) then
	
					temp, _ = gsub(tooltipText, SEASPELLBOOK_ENERGY.string, "%1")
					spellTable.energyCost = tonumber( temp )
	
				--	# Rage
				elseif runLevel == 2 and runSide == 1 and
					SEASPELLBOOK_RAGE.func(tooltipText, SEASPELLBOOK_RAGE.string ) then
	
					temp, _ = gsub(tooltipText, SEASPELLBOOK_RAGE.string, "%1")
					spellTable.rageCost = tonumber( temp )
	
				--	10 sec cast
				elseif runLevel >= 2 and runLevel <= 3 and runSide == 1 and
					SEASPELLBOOK_CASTTIME.func( tooltipText, SEASPELLBOOK_CASTTIME.string ) then
	
					temp, _ = gsub( tooltipText, SEASPELLBOOK_CASTTIME.string, "%1" )
					spellTable.castTime = tonumber( temp )
	
				--	8-25 yd range
				elseif ( runLevel == 2 and runSide == 1 or runSide == 2 ) and
					SEASPELLBOOK_RANGEMINMAX.func( tooltipText, SEASPELLBOOK_RANGEMINMAX.string ) then
	
					_, _, spellTable.minRange, spellTable.maxRange = string.find( tooltipText, SEASPELLBOOK_RANGEMINMAX.string )
	
					spellTable.maxRange = tonumber( spellTable.maxRange )
					spellTable.minRange = tonumber( spellTable.minRange )
	
				--	5 yd range
				elseif ( runLevel == 2 and runSide == 1 or runSide == 2 ) and
					SEASPELLBOOK_RANGE.func( tooltipText, SEASPELLBOOK_RANGE.string ) then
	
					temp, _ = gsub( tooltipText, SEASPELLBOOK_RANGE.string, "%1" )
					spellTable.maxRange = tonumber( temp )
	
				--	Requires Cat Form
				elseif runLevel >= 2 and runLevel <= 5 and runSide == 1 and
					SEASPELLBOOK_REQUIRES.func( tooltipText, SEASPELLBOOK_REQUIRES.string ) then
	
					if spellTable.requires then
						spellTable.requires = spellTable.requires .. ", " .. gsub( tooltipText, SEASPELLBOOK_REQUIRES.string, "%1" )
					else
						spellTable.requires = gsub( tooltipText, SEASPELLBOOK_REQUIRES.string, "%1" )
					end
	
				--	Tools: |cffff2020Flint and Tinder|r
				elseif runLevel >= 3 and runLevel <= 4 and runSide == 1 and
					SEASPELLBOOK_TOOLS.func( tooltipText, SEASPELLBOOK_TOOLS.string ) then
	
					spellTable.tools = gsub( tooltipText, SEASPELLBOOK_TOOLS.string, "%1" )
	
				--	Reagents: |cffff2020Simple Wood|r
				elseif runLevel >= 3 and runLevel <= 4 and runSide == 1 and
					SEASPELLBOOK_REAGENTS.func( tooltipText, SEASPELLBOOK_REAGENTS.string ) then
	
					spellTable.reagents = gsub( tooltipText, SEASPELLBOOK_REAGENTS.string, "%1" )
	
				--	# min cooldown
				elseif runSide == 2 and
					SEASPELLBOOK_COOLDOWN_MIN.func( tooltipText, SEASPELLBOOK_COOLDOWN_MIN.string ) then
	
					_, _, spellTable.cooldown, _ = string.find( tooltipText, SEASPELLBOOK_COOLDOWN_MIN.string )
					spellTable.cooldown = 60 * spellTable.cooldown
	
				--	# sec cooldown
				elseif runSide == 2 and
					SEASPELLBOOK_COOLDOWN_SEC.func( tooltipText, SEASPELLBOOK_COOLDOWN_SEC.string ) then
	
					_, _, spellTable.cooldown, _ = string.find( tooltipText, SEASPELLBOOK_COOLDOWN_SEC.string )
					spellTable.cooldown = tonumber( spellTable.cooldown )
	
				--	Description
				elseif runLevel >= 2 and runLevel <= 6 and runSide == 1 then
					spellTable.description = tooltipText
	
				end
			end
		end
	
		if SEA_SPELLBOOK_DEBUG then
			spellTable.debug = {}
			for i = 1, SeaSpellbookTooltip:NumLines() do
				spellTable.debug["R"..i] = getglobal( "SeaSpellbookTooltipTextRight" .. i):GetText()
				spellTable.debug["L"..i] = getglobal( "SeaSpellbookTooltipTextLeft" .. i):GetText()
			end
		end
	end
	
	--
	-- GetSpellIDByName( name )
	--	name: local spell name.
	--
	Sea.wow.spellbook.GetSpellIDByName = function( name, booktype, rank )
		if not Sea.wow.spellbook.spell[name] or
			( booktype and booktype ~= BOOKTYPE_SPELL and booktype ~= BOOKTYPE_PET ) or
			rank and not tonumber( rank )
		then
			return null
		end
		if not booktype then
			booktype = BOOKTYPE_SPELL
		end
		if not rank then
			rank = 0
		end
	
		return Sea.wow.spellbook[booktype][name][rank].ID
	end
	
	
	--
	-- Optional Sea.io support
	--
	if Sea.io and Sea.io.print and Sea.io.dprint then
		Sea.wow.spellbook.print = Sea.io.print
		Sea.wow.spellbook.dprint = Sea.io.dprint
	else
		local function nilFunction() end
		Sea.wow.spellbook.print = nilFunction
		Sea.wow.spellbook.dprint = nilFunction
	end
	
	
	--
	-- ShortCut
	--
	SeaSpellbook = Sea.wow.spellbook
	
	
	--
	-- Compare two values and return true or false
	--
	local function SeaSpellbook_Compare(var1, var2)
		if var1 == var2 then
			return true
		else
			return false
		end
	end
	
	--
	-- Find pattern var2 in var1
	--
	local function SeaSpellbook_FindPattern(var1, var2)
		if string.find(var1, var2) then
			return true
		else
			return false
		end
	end
	
	--
	-- Everything here is localized by using GlobalStrings.lua
	--
	SEASPELLBOOK_INSTANT = {
		string = SPELL_CAST_TIME_INSTANT_NO_MANA,
		func = SeaSpellbook_Compare,
	}
	SEASPELLBOOK_INSTANTCAST = {
		string = SPELL_CAST_TIME_INSTANT,
		func = SeaSpellbook_Compare,
	}
	SEASPELLBOOK_NEXTMELEE = {
		string = SPELL_ON_NEXT_SWING,
		func = SeaSpellbook_Compare,
	}
	SEASPELLBOOK_NEXTRANGED = {
		string = SPELL_ON_NEXT_RANGED,
		func = SeaSpellbook_Compare,
	}
	SEASPELLBOOK_CRITCHANCE = {
		string = gsub(CHANCE_TO_CRIT, "%%%.2f%%%%", "(%%d+.%%d+)%%%%"),
		func = SeaSpellbook_FindPattern,
	}
	SEASPELLBOOK_DODGECHANCE = {
		string = gsub(CHANCE_TO_DODGE, "%%%.2f%%%%", "(%%d+.%%d+)%%%%"),
		func = SeaSpellbook_FindPattern,
	}
	SEASPELLBOOK_PARRYCHANCE = {
		string = gsub(CHANCE_TO_PARRY, "%%%.2f%%%%", "(%%d+.%%d+)%%%%"),
		func = SeaSpellbook_FindPattern,
	}
	SEASPELLBOOK_BLOCKCHANCE = {
		string = gsub(CHANCE_TO_BLOCK, "%%%.2f%%%%", "(%%d+.%%d+)%%%%"),
		func = SeaSpellbook_FindPattern,
	}
	SEASPELLBOOK_MANA = {
		string = gsub(MANA_COST, "%%d", "(%%d)"),
		func = SeaSpellbook_FindPattern,
	}
	SEASPELLBOOK_FOCUS = {
		string = gsub(FOCUS_COST, "%%d", "(%%d)"),
		func = SeaSpellbook_FindPattern,
	}
	SEASPELLBOOK_MANAALL = {
		string = SPELL_USE_ALL_MANA,
		func = SeaSpellbook_Compare,
	}
	SEASPELLBOOK_ENERGY = {
		string = gsub(ENERGY_COST, "%%d", "(%%d)"),
		func = SeaSpellbook_FindPattern,
	}
	SEASPELLBOOK_RAGE = {
		string = gsub(RAGE_COST, "%%d", "(%%d)"),
		func = SeaSpellbook_FindPattern,
	}
	SEASPELLBOOK_CASTTIME = {
		string = gsub(SPELL_CAST_TIME_SEC, "%%%.3g", "(%%d%%%.%?%%d%*)"),
		func = SeaSpellbook_FindPattern,
	}
	SEASPELLBOOK_RANGE = {
		string = gsub(SPELL_RANGE, "%%s", "(%%d)"),
		func = SeaSpellbook_FindPattern,
	}
	SEASPELLBOOK_REQUIRES = {
		string = "^" .. gsub(SPELL_EQUIPPED_ITEM, "%%s", "(.+)"),
		func = SeaSpellbook_FindPattern,
	}
	SEASPELLBOOK_TOOLS = {
		string = SPELL_TOTEMS .. "(.+)",
		func = SeaSpellbook_FindPattern,
	}
	SEASPELLBOOK_REAGENTS = {
		string = SPELL_REAGENTS .. "(.+)",
		func = SeaSpellbook_FindPattern,
	}
	SEASPELLBOOK_RANGEMINMAX = {
		string = gsub(SPELL_RANGE, "%%s", "(%%d+)%%-(%%d+)"),
		func = SeaSpellbook_FindPattern,
	}
	SEASPELLBOOK_COOLDOWN_MIN = {
		string = gsub(SPELL_RECAST_TIME_MIN, "%%.3g", "(%%d*.*%%d)"),
		func = SeaSpellbook_FindPattern,
	}
	SEASPELLBOOK_COOLDOWN_SEC = {
		string = gsub(SPELL_RECAST_TIME_SEC, "%%.3g", "(%%d*.*%%d)"),
		func = SeaSpellbook_FindPattern,
	}
	SEASPELLBOOK_CHANNELED = {
		string = SPELL_CAST_CHANNELED,
		func = SeaSpellbook_Compare,
	}

end
