local table = require "table"
local oo = require "loop.base"
local Entity = require "LuaOrm.Entity"
local pluto = require "pluto"
local type = type
local ipairs = ipairs
local pairs = pairs
local print = print

module("LuaOrm.PagedRequest", oo.class)

--/////////////////////////////////////////////////////////////////////////////
--
local function GetRows(self, lazy)
	local query = self.m_DataSource:BuildPagedQuery(self.m_condition, self.m_tables, self.m_fields, 
													self.m_order, self.m_rowsPerPage, self.m_currentPage,
													self.m_hasRelationship)
	local rows = self.m_DataSource:FetchRows(self.m_model, query)
	if not rows then
		return {}
	end
	for k, row in pairs(rows) do
		rows[k] = self.m_model:CreateEntityFromRow(row, lazy) 
	end
	collectgarbage()
	return rows
end
--/////////////////////////////////////////////////////////////////////////////
--
function NextPage(self)
    if (self.m_currentPage >= self.m_topPage) then
        return nil
    end
    self.m_currentPage = self.m_currentPage + 1
    return GetRows(self)
end
--/////////////////////////////////////////////////////////////////////////////
--
function PreviousPage(self)
    if (self.m_currentPage <= 1) then
        return nil
    end
    self.m_currentPage = self.m_currentPage - 1
    return GetRows(self)
end
--/////////////////////////////////////////////////////////////////////////////
--
function GetPage(self, pageNumber, lazy)
    if (pageNumber == nil or pageNumber < 1 or pageNumber > self.m_topPage) then
        pageNumber = 1
    end
    self.m_currentPage = pageNumber
    return GetRows(self, lazy)
end
--/////////////////////////////////////////////////////////////////////////////
--
function Serialize(self)
	local persistable = {}
	persistable.m_modelname = self.m_model.name
	persistable.m_tables = self.m_tables	
	persistable.m_currentPage = self.m_currentPage	
	persistable.m_condition = self.m_condition	
	persistable.m_fields = self.m_fields	
	persistable.m_rowsPerPage = self.m_rowsPerPage	
	persistable.m_order = self.m_order	
	persistable.m_topPage = self.m_topPage	
	persistable.m_totalRows = self.m_totalRows
	persistable.m_hasRelationship = self.m_hasRelationship

	return pluto.persist({}, persistable)
end
--/////////////////////////////////////////////////////////////////////////////
--
function Deserialize(self, buffer, datasource, model)
	local persistable = pluto.unpersist({}, buffer)
	if (model) then
		self.m_model = model
	else
		self.m_model = orbit.mapper.models[persistable.m_modelname]
	end
	self.m_tables = persistable.m_tables	
	self.m_currentPage = persistable.m_currentPage	
	self.m_condition = persistable.m_condition	
	self.m_fields = persistable.m_fields	
	self.m_rowsPerPage = persistable.m_rowsPerPage	
	self.m_order = persistable.m_order	
	self.m_topPage = persistable.m_topPage	
	self.m_totalRows = persistable.m_totalRows
	self.m_hasRelationship = persistable.m_hasRelationship
	self.m_DataSource = datasource	
end
--/////////////////////////////////////////////////////////////////////////////
--
function GetNumberOfPages(self)
    return self.m_topPage
end
--/////////////////////////////////////////////////////////////////////////////
--
function Initialize(self, model, condition, tables, fields, order, rowsPerPage, hasRelationship)
	self.m_DataSource = model.dataSource
    self.m_currentPage = 0
    self.m_model = model
    self.m_condition = condition
    self.m_tables = tables
    self.m_fields = fields
    self.m_rowsPerPage = rowsPerPage
    self.m_hasRelationship = hasRelationship
	if (not order) then
		for k, v in pairs(model.primaryKey) do
			self.m_order = (self.m_order and self.m_order .. ", " or "") .. self.m_DataSource.Format("%Q.%Q", model.name, v)
		end
    else
        self.m_order = order
	end 
    self.m_topPage, self.m_totalRows = self.m_DataSource:GetPagesInQuery(self.m_condition, self.m_tables, self.m_fields, self.m_order, self.m_rowsPerPage, hasRelationship)
end
