GHU_Spellbook = {}
GHU_Spellbook.hooked = {}
GHU_Spellbook.spells = {};
GHU_Spellbook.tabs = {};

-- 	standard
function GHU_Spellbook:Create(name)
		
	local obj = setmetatable({},{__index = GHU_Spellbook});
	
	-- initialize variables
	obj.name = name; -- example
	
	
		
	HookObj = obj;
	obj:InitHooks("HookObj");
	HookObj = nil;  
	
	return obj
end
	
function GHU_Spellbook:Hook(funcName,varName)
	
	if not(type(self.orig)=="table") then self.orig ={}; end
	assert(type(self[funcName])=="function","No function found for "..funcName);
	self.orig[funcName] = _G[funcName];
		
	RunScript("local t = _G[\""..varName.."\"]; t[\"hooked\"][\""..funcName.."\"] = function(...) gself = _G[\""..varName.."\"]; local f = _G[\""..varName.."\"]; return f:"..funcName.."(...); end _G[\""..varName.."\"]=t; ");
	_G[funcName]=_G[varName]["hooked"][funcName];
end

function GHU_Spellbook:InitHooks(varName)
	if not(self.isHooked) then
		local obj = _G[varName];
		
		-- list of functions to hook
		-- self:Hook("GetTradeSkillLine",varName) -- just an example

		self:Hook("IsConsumableSpell",varName) --isConsumable = IsConsumableSpell(index, "bookType") or IsConsumableSpell("name")
		self:Hook("GetSpellCount",varName)---numCasts = GetSpellCount(index, "bookType") or GetSpellCount("name")
        self:Hook("IsHarmfulSpell",varName)---isHarmful = IsHarmfulSpell(index, "bookType") or IsHarmfulSpell("name")
	    --getting function not found error--self:Hook("IsCurrentSpell",varName)---isCurrent = IsCurrentSpell(index, "bookType") or IsCurrentSpell("name")
		self:Hook("GetNumTabs",varName)---lal numTabs = GetNumSpellTabs()
		self:Hook("IsHelpfulSpell",varName)---isHelpful = IsHelpfulSpell(index, "bookType") or IsHelpfulSpell("name")
	    self:Hook("GetSpellInfo",varName)---name, rank, icon, powerCost, isFunnel, powerType,
									--castingTime, minRange, maxRange = GetSpellInfo(index, "bookType") or GetSpellInfo("name") or GetSpellInfo(id)
		self:Hook("IsSpellInRange",varName)---inRange = IsSpellInRange(index, "bookType", "unit") or IsSpellInRange("name", "unit")
		self:Hook("IsUsableSpell",varName)---isUsable, notEnoughMana = IsUsableSpell(index, "bookType") or IsUsableSpell("name")
		--self:Hook("SepllCanTargetItem",varName)---canTarget = SpellCanTargetItem()Returns whether the spell currently awaiting a target requires an item to be chosen. Only applies when the player has attempted to
				------------------------------------cast a spell but the spell requires a target before it can begin casting
		self:Hook("SpellCanTargetUnit",varName)----canTarget = SpellCanTargetUnit("unit") or SpellCanTargetUnit("name")
         self:Hook("SpellHasRange",varName)----hasRange = SpellHasRange(index, "bookType") or SpellHasRange("name")
	    --self:Hook("SpellIsTargeting",varName) --Returns whether a spell is currently awaiting a target
					--Signature:
				--isTargeting = SpellIsTargeting()
	    self:Hook("CursorHasSpell",varName)---hasSpell = CursorHasSpell()
		self:Hook("GetSpellLink",varName)---link, tradeLink = GetSpellLink(index, "bookType") or GetSpellLink("name") or GetSpellLink(id)
				--CATAFUNCS--
				--[[
		self:Hook("GetSpellBookItemInfo",varName)---local slotType = GetSpellBookItemInfo(slot, SpellBookFrame.bookType);
		self:Hook("GetSpellBookItemTexture",varName)---local texture = GetSpellBookItemTexture(spellIndex, SpellBookFrame.bookType);
		self:Hook("GetSpellItemName",varName)---local spellName, subSpellName = GetSpellBookItemName(spellIndex, SpellBookFrame.bookType);
		self:Hook("IsPassiveSpell",varName)---local isPassive = IsPassiveSpell(spellIndex, SpellBookFrame.bookType);
		--self:Hook("IsSelectedSpellBookItem",varName)---IsSelectedSpellBookItem(slot, SpellBookFrame.bookType)
				---PickupSpellBookItem(slot, SpellBookFrame.bookType);
				---SetSpellbookPetAction
		self:Hook("GetSpellCooldown",varName)---local start, duration, enable = GetSpellCooldown(spellIndex, SpellBookFrame.bookType);
]]--
		
		
		self.spells = {};
	     self.index = {};
		 self.tabs = {};
		self.isHooked = true;
	end
end
--[[BookTypes
spell,pet,profession,mount,companion
]]

-- =================	Control of display  ==============
--[[These functions is used to decide if the quest information from this.
	Quest Log object is being shown, or if the original values is being shown.
	
	When the self.shown value is true, then the hooked function should return 
	the modified value. Otherwise it should return the original function.
--]]
function GHU_Spellbook:Show() 
	GHU_Spellbook.shown = true;
	--unsure of the update func for this
end

function GHU_Spellbook:Hide()
	GHU_Spellbook.shown = nil;
	
end
-- =========== Hook functions ==================

function GHU_Spellbook:IsConsumableSpell(index,bookType)--also is can just take 'name' so index can be that too?
self = gself;
if self.shown==true then
if not bookType then--its a name/refID
return self.spells[index].consumable;
end
end

return self.orig.IsConsumableSpell(index,bookType)
end

function GHU_Spellbook:GetSpellCount(index,bookType)--also is can just take 'name' so index can be that too?
self = gself;

if self.shown==true then
if not bookType then--its a name/refID
local reag = self.spells[index].reagent
local spellcasts;

--PSUDEO CODE
--[[If <fine GH spell reagent> > reag then
spellcasts=reag divided by the numbe of reagents on hand
]]

spellcasts = 10;--need a defualt number for no reagent needed.

return spellcasts;
end
end


return self.orig.GetSpellCount(index,bookType)
end

function GHU_Spellbook:IsHarmfulSpell(index,bookType)--also is can just take 'name' so index can be that too?
self = gself;

if self.shown==true then
if not bookType then--its a name/refID
return self.spells[index].IsHarmful;
end
end

return self.orig.IsHarmfulSpell(index,bookType)
end

function GHU_Spellbook:GetNumTabs()--called as a function with no args to get number of tabs
self = gself;
if self.shown==true then
local tab = 0;

for k,v in pairs(self.tabs) do
tab=tab+1;
end
return tab

end


return self.orig.GetNumTabs()
end

function GHU_Spellbook:IsHelpfulSpell(index,bookType)--also is can just take 'name' so index can be that too?
self = gself;

if self.shown==true then
if not bookType then--its a name/refID
return self.spells[index].IsHelpful;
end
end
return self.orig.IsHelpfulSpell(index,bookType)
end

function GHU_Spellbook:GetSpellInfo(index,bookType)--also is can just take 'name' so index can be that too?this one also can just be id
self = gself;

if self.shown==true then
if not bookType then--its a name/refID
--name, rank, icon, powerCost, isFunnel, powerType,
--castingTime, minRange, maxRange = GetSpellInfo(index, "bookType") or GetSpellInfo("name") or GetSpellInfo(id)
--minrange, range to be in to cast, max range range beofro your out of range.
return self.spells[index].name,self.spells[index].rank,self.spells[index].icon,self.spells[index].powercost,
self.spells[index].isFunnel,self.spells[index].powerType,self.spells[index].castTime,self.spells[index].minrRangeself.spells[index].maxRange;
end
end
return self.orig.GetSpellInfo(index,bookType)
end

function GHU_Spellbook:IsSpellInRange(index,bookType)--also is can just take 'name' so index can be that too?
self = gself;

if self.shown==true then
if not bookType then--its a name/refID
local inRange = false;
local minR = self.spells[index].minRange
local maxR = self.spells[index].maxRange
--math based on target range or an AOE range here

return inRange;
end
end

return self.orig.IsSpellInRange(index,bookType)
end

function GHU_Spellbook:IsUsableSpell(index,bookType)--also is can just take 'name' so index can be that too?
self = gself;

if self.shown==true then
if not bookType then--its a name/refID
--base on powercost?
return self.spells[index].IsHelpful;
end
end

return self.orig.IsUsableSpell(index,bookType)
end

function GHU_Spellbook:SpellCanTargetUnit(name)---spell name or unit
self = gself;

---unsure

return self.orig.SpellCanTargetUnit(index,bookType)
end

function GHU_Spellbook:SpellHasRange(index,bookType)--also is can just take 'name' so index can be that too?
self = gself;

if self.shown==true then
if not bookType then--its a name/refID
local range = false;
if self.spells[index].minRange ~= (nil or 0) and self.spells[index].maxReange ~= (nil or 0) then
range=true;
end
return range;

end
end

return self.orig.SpellHasRange(index,bookType)
end

function GHU_Spellbook:CursorHasSpell()---truefalse function
self = gself;
return self.orig.CursorHasSpell()
end

function GHU_Spellbook:GetSpellLink(index,bookType)--also is can just take 'name' so index can be that too?
self = gself;

--no idea how to make links
return self.orig.GetSpellLink(index,bookType)
end


function GHU_Spellbook:GetSpellbookItemInfo(index,bookType)--also is can just take 'name' so index can be that too?
self = gself;
--returns slotType, so just return refID?

if self.shown==true then
if not bookType then--its a name/refID
return self.spells[index].school --?
end
end

return self.orig.GetSpellbookItemInfo(index,bookType)
end

function GHU_Spellbook:GetSpellbookItemTexture(index,bookType)--also is can just take 'name' so index can be that too?
self = gself;

if self.shown==true then
if not bookType then--its a name/refID
return self.spells[index].icon;
end
end

return self.orig.GetSpellbookItemName(index,bookType)
end

function GHU_Spellbook:IsPassiveSpell(index,bookType)--also is can just take 'name' so index can be that too?
self = gself;

if self.shown==true then
if not bookType then--its a name/refID
return self.spells[index].IsPassive;
end
end

return self.orig.IsPassiveSpell(index,bookType)
end

function GHU_Spellbook:GetSpellCooldown(index,bookType)--also is can just take 'name' so index can be that too?
self = gself;
if self.shown==true then
if not bookType then--its a name/refID
---local start, duration, enable
return self.spells[index].cooldown;
end
end
return self.orig.GetSpellCooldown(index,bookType)
end


-- =========== Internal functions ==================

---Make SpellBook frames?
function GHU_SpellBookSetupTabs(refID,num)
self = gself;
--self:Hook("SpellBookSkillLineTab_OnClick");

--"SpellBookSkillLineTabTemplate"

--"SpellBookFrameTabButtonTemplate"

local shown;
if not(SpellBookSkillLineTab1:IsShown()) then
		shown = 0;
	elseif not(SpellBookSkillLineTab2:IsShown()) and not(SpellBookSkillLineTab3:IsShown()) and not(SpellBookSkillLineTab4:IsShown()) then -- should not happend
		shown = 1;
	elseif SpellBookSkillLineTab2:IsShown() and SpellBookSkillLineTab3:IsShown() and SpellBookSkillLineTab4:IsShown() then     
	if SpellBookSkillLineTab5:IsShown() then --guild tab
		shown = 5;
             else
              shown = 4;
			  end
	
	end


local newtab = shown + newtab ;

local f = CreateFrame("CheckButton","GHU_SpellTab"..num,SpellBookFrame,"SpellBookSkillLineTabTemplate");

f:SetPoint("TOPLEFT",self.tabs[newtab-1],"BOTTOMLEFT",0,-22)

self.tabs[refID].frame = f;

end

function GHU_SetupSpellBtn()
local spellTabname,spellTabtexture,offset,numSpells=GetSpellTabInfo(1);--it takes index of the spell tab we're looking at

print(SpellBook_GetCurrentPage());



local page,totalpage = SpellBook_GetCurrentPage()

local parent = (numSpells+offset)-12
--Each page has 12 slots so you have to put it in the right spot.
if totalpage > 1 and page ~= 1 then
if offset==0 then offset = 2 end;
parent = (numSpells+offset)-12
setpage = page
end
local button = "SpellButton"..parent;


--i was trying to make a unique identifier name but it kept erroring out on me.

--may need to hook SpellButton_ OnEnter,click ETC;
print(button)


local f = CreateFrame("CheckButton","GHU_BSpellBTN",SpellBookFrame,"SecureFrameTemplate, SpellButtonTemplate");
f:SetPoint("Bottom",button)

f:SetText("test")
-- f:SetTexture("\\Interf")
if not page then
f:Hide()
else
f:Show()

end
end

-- =========== API functions ==================
--AddBook
--AddSchool
--AddSpell
--name, rank, icon, powerCost, isFunnel, powerType,
--castingTime, minRange, maxRange = GetSpellInfo(index, "bookType") or GetSpellInfo("name") or GetSpellInfo(id)
function GHU_Spellbook:AddSpell(refID,name,rank, powerCost, isFunnel, powerType,castTime, minRange, maxRange,IsPassive,cooldown,consumable,school)

self = gself;
table.insert(GHU_Spellbook.spells[refID],{
		name=name,
		rank=rank,
		powerCost=powerCost,
		isFunnel=nil, 
		powerType=powerType,
		castTime=catTime, 
		minRange=minRange,
		maxRange=maxRange,
		IsPassive=IsPassive,
		cooldown=cooldown,
		consumable=consumable,
		school=school,
  });
--add reagents in another function_?
end


function GHU_Spellbook:AddTab(refID,name,num)
table.insert(self.tabs[refID],{
		name=name,
		num=num,
		frame=nil;
  });
  
GHU_SpellBookSetupTabs(refID,num)
  
end
--Remove for above
--Other?
