local Page = Object:extend()

local function updateWidgetByOrder(a, b)
    if a.order ~= b.order then
        return a.order < b.order
    else
        return a.creationID < b.creationID
    end
end

-- INIT FUNCTIONS
-- Initialize and basic functions.

function Page:new()
    self.widgets = {}
    self.selected = 0
    self.selectedPrevious = 0
    self.cancel = 0
    self.limit = -1
    self.parent = nil
    -- self:updateWidgetSize()
end

function Page:clear()
    self.widgets = {}
    self.cancel = 0
end

function Page:setLimit(limit)
    self.limit = limit
end

-- PAGE FUNCTIONS
-- functions to handle other pages

function Page:setParent(parent)
    self.parent = parent
end

function Page:getParent()
    return self.parent
end

-- UPDATE/DRAW FUNCTIONS
-- All the update functions

function Page:update(dt)
    self:removeDestroyedWidgets()
    for id, widget in ipairs(self.widgets) do
        widget.id = id
        widget:update(dt)
    end
end

function Page:updateWidgetsOrder()
    table.sort(self.widgets, updateWidgetByOrder)
end

function Page:updateWidgetsID()
    for id, widget in ipairs(self.widgets) do
        widget.id = id
    end
end

-- ACTION FUNCTIONS
-- All the actions callback used by the widgets

function Page:cancelAction()
    if (self.cancel ~= 0) then
        self:action(self.cancel, "key")
    end
end

function Page:action(id, type)
    if (self:widgetExist(id)) then
        self.widgets[id]:action(type)
    end
end

function Page:selectedAction()
    if (self.selected ~= 0) then
        self:action(self.selected, "key")
    end
end

-- WIDGET FUNCTIONS
-- All the functions to handle widgets

function Page:addWidget(newWidget)
    if (self.limit ~= -1 and #self.widgets >= self.limit) then
        return
    end
    if #self.widgets == 0 then
        self.selected = 1
    end
    table.insert(self.widgets, newWidget)
    self:updateWidgetsID()
    self:updateWidgetsOrder()
end

function Page:getList(first, lenght)
    local listWidget = {}
    local first = first or 1
    local lenght = lenght or #self.widgets
    lenght = math.min(lenght, (#self.widgets + 1 - first))
    local last = (first + lenght - 1)

    for i = first, (last) do
        table.insert(listWidget, self.widgets[i])
    end

    return listWidget
end

function Page:removeDestroyedWidgets() -- On retire les widgets marquées comme supprimées
    for i, v in ipairs(self.widgets) do
        if (v.destroyed == true) then
            table.remove(self.widgets, i)
        end
    end
end

function Page:lenght()
    return #self.widgets
end

function Page:widgetExist(id)
    local id = id or 0
    return (id >= 1 and id <= #self.widgets)
end

-- CANCEL FUNCTIONS
-- Add a widget as a "cancel" function 

function Page:setCancelWidget(id)
    self.cancel = #self.widgets
end

function Page:getCancelWidget(id)
    return self.cancel
end

-- CURSOR FUNCTIONS
-- Set or move the cursor of the menu

function Page:getSelected()
    return self.selected
end

function Page:haveCursor()
    return self:widgetExist(self.selected)
end

function Page:trySelectWidget(cursorid)
    if (self:widgetExist(cursorid)) then
        self:setCursor(cursorid)
        return true
    else
        return false
    end
end

function Page:setCursor(cursorid)
    self.selected = cursorid --math.max(1, math.min(cursorid, #self.widgets))
end

function Page:moveCursorAbsolute(newSelected)
    -- self:playNavigationSound()
    if newSelected < 1 then
        self.selected = #self.widgets + newSelected
    else
        if newSelected > #self.widgets then
            self.selected = newSelected - #self.widgets
        else
            self.selected = newSelected
        end
    end
end

function Page:moveCursor(relative)
    self:moveCursorAbsolute(self.selected + relative)
end


return Page
