---@class Panner
Panner = {}

local function panCoroutine(ball)
    local offset = utils.xy(getDrawOffset(ball.x, ball.y))
    while true do
        local target, deltaSeconds = coroutine.yield(offset.x, offset.y)
        if target == nil then
            offset = utils.xy(getDrawOffset(ball.x, ball.y))
        else
            while utils.moveAtSpeed(offset, 200 * deltaSeconds, target, 20) do
                target, deltaSeconds = coroutine.yield(offset.x, offset.y)
            end
            -- -- Pan back to ball
            -- while utils.moveAtSpeed(offset, 200 * deltaSeconds, ball, 20) do
            --     target, deltaSeconds = coroutine.yield(offset.x, offset.y)
            -- end
        end
    end
end

---@param ball XyPair
function Panner.new(ball)
    return setmetatable({
        coroutine = coroutine.create(function()
            panCoroutine(ball)
        end),
        panTarget = nil,
    }, { __index = Panner })
end

---@param deltaSeconds number
---@return number offsetX, number offsetY
function Panner:get(deltaSeconds)
    if self.holdUntil and self.holdUntil() then
        self:reset()
    end
    local _, offsetX, offsetY = coroutine.resume(self.coroutine, self.panTarget, deltaSeconds)
    return offsetX, offsetY
end

---@param panTarget XyPair
---@param holdUntil fun(): boolean
function Panner:panTo(panTarget, holdUntil)
    self.panTarget = panTarget
    self.holdUntil = holdUntil
end

function Panner:reset()
    self.holdUntil = nil
    self.panTarget = nil
end
