-- @docclass
UIPopupScrollMenu = extends(UIWidget, 'UIPopupScrollMenu')

local currentMenu

function UIPopupScrollMenu.create()
    local menu = UIPopupScrollMenu.internalCreate()

    local scrollArea = g_ui.createWidget('UIScrollArea', menu)
    scrollArea:setLayout(UIVerticalLayout.create(menu))
    scrollArea:setId('scrollArea')

    local scrollBar = g_ui.createWidget('VerticalScrollBar', menu)
    scrollBar:setId('scrollBar')
    scrollBar.pixelsScroll = false

    scrollBar:addAnchor(AnchorRight, 'parent', AnchorRight)
    scrollBar:addAnchor(AnchorTop, 'parent', AnchorTop)
    scrollBar:addAnchor(AnchorBottom, 'parent', AnchorBottom)

    scrollArea:addAnchor(AnchorLeft, 'parent', AnchorLeft)
    scrollArea:addAnchor(AnchorTop, 'parent', AnchorTop)
    scrollArea:addAnchor(AnchorBottom, 'parent', AnchorBottom)
    scrollArea:addAnchor(AnchorRight, 'next', AnchorLeft)
    scrollArea:setVerticalScrollBar(scrollBar)

    menu.scrollArea = scrollArea
    menu.scrollBar = scrollBar
    return menu
end

function UIPopupScrollMenu:setScrollbarStep(step)
    self.scrollBar:setStep(step)
end

function UIPopupScrollMenu:display(pos)
    -- don't display if not options was added
    if self.scrollArea:getChildCount() == 0 then
        self:destroy()
        return
    end

    if g_ui.isMouseGrabbed() then
        self:destroy()
        return
    end

    if currentMenu then
        currentMenu:destroy()
    end

    if pos == nil then
        pos = g_window.getMousePosition()
    end

    rootWidget:addChild(self)
    self:setPosition(pos)
    self:grabMouse()
    currentMenu = self
end

function UIPopupScrollMenu:onGeometryChange(newRect, oldRect)
    local parent = self:getParent()
    if not parent then
        return
    end
    local ymax = parent:getY() + parent:getHeight()
    local xmax = parent:getX() + parent:getWidth()
    if newRect.y + newRect.height > ymax then
        local newy = newRect.y - newRect.height
        if newy > 0 and newy + newRect.height < ymax then
            self:setY(newy)
        end
    end
    if newRect.x + newRect.width > xmax then
        local newx = newRect.x - newRect.width
        if newx > 0 and newx + newRect.width < xmax then
            self:setX(newx)
        end
    end
    self:bindRectToParent()
end

function UIPopupScrollMenu:addOption(optionName, optionCallback, shortcut)
    local optionWidget = g_ui.createWidget(self:getStyleName() .. 'Button', self.scrollArea)
    optionWidget.onClick = function(widget)
        self:destroy()
        optionCallback()
    end
    optionWidget:setText(optionName)
    local width = optionWidget:getTextSize().width + optionWidget:getMarginLeft() + optionWidget:getMarginRight() + 15

    if shortcut then
        local shortcutLabel = g_ui.createWidget(self:getStyleName() .. 'ShortcutLabel', optionWidget)
        shortcutLabel:setText(shortcut)
        width = width + shortcutLabel:getTextSize().width + shortcutLabel:getMarginLeft() +
                    shortcutLabel:getMarginRight()
    end

    self:setWidth(math.max(self:getWidth(), width))
end

function UIPopupScrollMenu:addSeparator()
    g_ui.createWidget(self:getStyleName() .. 'Separator', self.scrollArea)
end

function UIPopupScrollMenu:onDestroy()
    if currentMenu == self then
        currentMenu = nil
    end
    self:ungrabMouse()
end

function UIPopupScrollMenu:onMousePress(mousePos, mouseButton)
    -- clicks outside menu area destroys the menu
    if not self:containsPoint(mousePos) then
        self:destroy()
    end
    return true
end

function UIPopupScrollMenu:onKeyPress(keyCode, keyboardModifiers)
    if keyCode == KeyEscape then
        self:destroy()
        return true
    end
    return false
end

-- close all menus when the window is resized
local function onRootGeometryUpdate()
    if currentMenu then
        currentMenu:destroy()
    end
end
connect(rootWidget, {
    onGeometryChange = onRootGeometryUpdate
})
