

-- class list
local LinkedClass,Page,Line,Object,Table,Column,Row,Area,Text,Image,Texture,Script;


--===================================================
--										Document
--===================================================	
GHU_Document = {};
function GHU_Document:Create()
	local obj = setmetatable({},{__index = GHU_Document});
	
	obj.width, obj.height = 400,600;
	obj.pages = {Page:Create(obj,"p1",obj.width, obj.height)};
	obj.refCount = 1;
	obj.scripts = {};
	obj.gui = CreateFrame("Frame"); -- make it a scroll frame, eventually own scroll frame template with horizontal scroll.
	obj.currentPage = 1;
	obj.scale = 1;
	
	obj.gui:SetWidth(obj.width);
	obj.gui:SetHeight(obj.height);
	
	
	
	return obj;
end

function GHU_Document:Serialize()
	
end

function GHU_Document:Deserialize(t)
	-- removes all old data. Remember to hide all old frames
end

function GHU_Document:Show()
	self.currentPage = 1;

	foreach(self.scripts,function(o) o:OnShow(); end);
	foreach(self.pages,function(o) o:Hide(); end);	
	assert(self.currentPage and self.pages[self.currentPage],format("Can not find page %s.",self.currentPage));
	self.pages[self.currentPage]:Show();
	
	self.gui:Show();
end

function GHU_Document:Hide()
	foreach(self.pages,function(o) o:Hide(); end);
	self.gui:Hide();
end

function GHU_Document:SetEditable(editable)
	self.editable = editable;
	
end

function GHU_Document:IsEditable(editable)
	return self.editable;	
end

function GHU_Document:GetPage(ref)
	for _,area in pairs(self.pages) do
		if area.ref == ref then return area end;
	end
end

function GHU_Document:GetNextPage(ref)
	for i,area in pairs(self.pages) do
		if area.ref == ref then 
			return self.pages[i+1];
		end;
	end
end

function GHU_Document:GetPrevPage(ref)
	for i,area in pairs(self.pages) do
		if area.ref == ref then 
			return self.pages[i-1];
		end;
	end
end


--===================================================
--										Page
--===================================================	
Page = {}
function Page:Create(parent,ref,width,height)
	local obj = setmetatable({},{__index = Page});
	
	obj.ref = ref;
	obj.width,obj.height = width,height;
	obj.margins = {top = 20, buttom = 20, left = 20, right = 20};
	
	obj.roamingAreas = {Area:Create(obj,obj.ref.."header"),Area:Create(obj,obj.ref.."footer")};
	obj.linkedAreas = {Area:Create(obj,obj.ref.."a1")};
	obj.nameingCount = 1;
	
	
	-- Setup GUI and parent
	obj.gui = CreateFrame("Frame",nil,parent.gui);
	obj.gui.obj = obj;
	obj.parent = parent;
	
	
	
	return obj;
end

function Page:Show()
	obj.gui:Show();
end

function Page:Hide()
	obj.gui:Hide();
end

function Page:IsEditable(editable)
	return self.parent:IsEditable();
end

function Page:SetSize(width,height)

end

function Page:SetMargin(top,buttom,left,right)

end

function Page:GetArea(ref)
	for _,area in pairs(self.roamingAreas) do
		if area.ref == ref then return area end;
	end
	for _,area in pairs(self.linkedAreas) do
		if area.ref == ref then return area end;
	end
	
end

function Page:GetFirstArea()
	return self.linkedAreas[1];
end

function Page:GetLastArea()
	return self.linkedAreas[#(self.linkedAreas)];
end

-- Get the area following a given area
function Page:GetNextArea(ref)
	for i,area in pairs(self.linkedAreas) do
		if area.ref == ref then
			if i < #(self.linkedAreas) then
				return self.linkedAreas[i+1];
			else
				local nextPage = self.parent:GetNextPage(self.ref);
				if nextPage then
					return nextPage:GetFirstArea();
				else
					return;
				end
			end
		end
	end
end

-- Get the area before a given area
function Page:GetPrevArea(ref)
	for i,area in pairs(self.linkedAreas) do
		if area.ref == ref then
			if i > 1 then
				return self.linkedAreas[i-1];
			else
				local nextPage = self.parent:GetPrevPage(self.ref);
				if nextPage then
					return nextPage:GetLastArea();
				else
					return;
				end
			end
		end
	end
end


--===================================================
--										Area
--===================================================	
-- an area that contains , such as header, footer, main area. Columns are normally different areas.
Area = {}
function Area:Create(parent,ref)
	local obj = setmetatable({},{__index = Area});
	obj.ref = ref;
	
	-- Setup GUI and parent
	obj.gui = CreateFrame("Frame",nil,parent.gui);
	obj.gui.obj = obj;
	obj.parent = parent;
	
	obj.lines = {Line:Create(this,"L1")};
	
	return obj;
end

function Area:Serialize()

end

function Area:Deserialize(t)

end

function Area:SetPosition(width,height,x,y)
	if x and y then obj.gui:SetPoint("TOPLEFT",self.parent.gui,"TOPLEFT",x,y); end
	if width and height then obj.gui.SetWidth(width); obj.gui:SetHeight(height); end
end

-- Get the next line.
function Area:GetNextLine(ref,thisAreaOnly)
	
end

--===================================================
--										Line
--===================================================	
--	A line inside an area
Line = {}
function Line:Create(parent,ref)
	local obj = setmetatable({},{__index = Line});
	obj.ref = ref;
		
	return obj;
end

function Line:Serialize()

end

function Line:Deserialize(t)

end

function Line:GetHeight()
	-- loop trough all object and find the heighest
end


--===================================================
--										Object
--===================================================	

Object = {}
function Object:SetPosition_Bound()

end

function Object:SetPosition_Roaming()

end





--===================================================
--										Text 
--===================================================	
Text = setmetatable({},{__index = Object}) -- inheritate object
function Text:Create(parent,prevObj,nextObj)
	local obj = setmetatable({},{__index = Text});
	
	obj.nextObj = nextObj;
	obj.prevObj = prevObj;
	obj.reachedEOL = nil;
	
	-- setup parent and GUI
	obj.parent = parent;
	obj.gui = CreateFrame("EditBox",nil,parent.gui);
	obj.gui.obj = obj;
	
	-- notify prev and nextobj
	if nextObj then nextObj.prevObj = obj; end
	if prevObj then prevObj.nextObj = obj; end
	
	
	return obj;
end

function Text:Serialize()

end

function Text:Deserialize(t)

end

--===================================================
--										Table
--===================================================	

Table = setmetatable({},{__index = Object}) -- inheritate object
function Table:Create()
	local obj = setmetatable({},{__index = Table});
	
	return obj;
end

function Table:Serialize()

end

function Table:Deserialize(t)

end

-- Row

-- Column



function TestMe() return TextArea:Create(CreateFrame("Frame")) end


--===================================================
--										temp class test
--===================================================	

classTest = setmetatable({},{}) -- inheritate object
function classTest:Create()
	local obj = setmetatable({},{__index = classTest});
	obj.A = "1";
	obj.B = "2";
	return obj;
end

function classTest:Serialize()

end

function classTest:gettable_event(key)
  table = self;
	local h
	if type(table) == "table" then
		local v = rawget(table, key)
		if v ~= nil then 
			return v 
		end
		h = getmetatable(table).__index
		if h == nil then 
			return nil 
		end
	else
		h = getmetatable(table).__index
		if h == nil then
			error("e")
		end
	end
	if type(h) == "function" then
		return (h(table, key)) -- call the handler
	else 
		return h[key] -- or répeat operation on it
	end
end