---@class MainMenu
MainMenu = {
    ---@type { new: fun(settings: Settings): { update: fun(self) } }
    next = nil,
}
local gfx = playdate.graphics

local StartFont <const> = gfx.font.new("fonts/Roobert-20-Medium.pft")

--- Take control of playdate.update
--- Will replace playdate.update when the menu is done.
---@param next { new: fun(settings: Settings): { update: fun(self) } }
function MainMenu.start(next)
    MenuMusic:play(0)
    MainMenu.next = next
    playdate.update = MainMenu.update
end

local inningCountSelection = 3

local function startGame()
    local next = MainMenu.next.new({
        finalInning = inningCountSelection,
        homeTeamSprites = HomeTeamSprites,
        awayTeamSprites = AwayTeamSprites,
    })
    playdate.resetElapsedTime()
    transitionBetween(MainMenu, next)
    MenuMusic:setPaused(true)
end

local function pausingEaser(baseEaser)
    --- t: elapsedTime
    --- d: duration
    return function(t, b, c, d)
        local percDone = t / d
        if percDone > 0.9 then
            t = d
        elseif percDone < 0.1 then
            t = 0
        else
            t = (percDone - 0.1) * 1.25 * d
        end
        return baseEaser(t, b, c, d)
    end
end

local animatorX = gfx.animator.new(2000, 30, 350, pausingEaser(playdate.easingFunctions.linear))
animatorX.repeatCount = -1
animatorX.reverses = true

local animatorY = gfx.animator.new(2000, 60, 200, pausingEaser(utils.easingHill))
animatorY.repeatCount = -1
animatorY.reverses = true

local crankStartPos = nil

---@generic T
---@param array T[]
---@param crankPosition number
---@return T
local function arrayElementFromCrank(array, crankPosition)
    local i = math.ceil(#array * (crankPosition + 0.001) / 360)
    return array[i]
end

local currentLogo

--luacheck: ignore
function MainMenu:update()
    playdate.timer.updateTimers()
    crankStartPos = crankStartPos or playdate.getCrankPosition()

    gfx.clear()

    if playdate.getCrankChange() ~= 0 then
        local crankOffset = (crankStartPos - playdate.getCrankPosition()) % 360
        currentLogo = arrayElementFromCrank(Logos, crankOffset).image
        replaceAwayLogo(currentLogo)
    end

    if currentLogo then
        currentLogo:drawScaled(20, C.Center.y + 40, 3)
    end

    if playdate.buttonJustPressed(playdate.kButtonA) then
        startGame()
    end
    if playdate.buttonJustPressed(playdate.kButtonUp) then
        inningCountSelection = inningCountSelection + 1
    end
    if playdate.buttonJustPressed(playdate.kButtonDown) then
        inningCountSelection = inningCountSelection - 1
    end

    GameLogo:drawCentered(C.Center.x, 50)

    StartFont:drawTextAligned("Press A to start!", C.Center.x, 140, kTextAlignment.center)
    gfx.drawTextAligned("with " .. inningCountSelection .. " innings", C.Center.x, 190, kTextAlignment.center)

    local ball = {
        x = animatorX:currentValue(),
        y = animatorY:currentValue(),
        z = 6,
        size = 6,
    }

    local ballIsHeld = drawFielder(AwayTeamSprites, ball, 30, 200)
    ballIsHeld = drawFielder(HomeTeamSprites, ball, 350, 200, playdate.graphics.kImageFlippedX) or ballIsHeld

    -- drawFielder(AwayTeamSprites, { x = 0, y = 0, z = 0 }, ball.x, ball.y)
    if not ballIsHeld then
        gfx.setLineWidth(2)

        gfx.setColor(gfx.kColorWhite)
        gfx.fillCircleAtPoint(ball.x, ball.y, ball.size)

        gfx.setColor(gfx.kColorBlack)
        gfx.drawCircleAtPoint(ball.x, ball.y, ball.size)
    end
end
