---@class UserInput: InputHandler
---@field buttonControlledThrow: fun(throwFlyMs: number, forbidThrowHome: boolean): boolean didThrow
UserInput = {}

---@return UserInput
function UserInput.new(buttonControlledThrow)
    return setmetatable({
        buttonControlledThrow = buttonControlledThrow,
    }, { __index = UserInput })
end

function UserInput:update()
    self.crankChange = playdate.getCrankChange()
    local crankLimited = self.crankChange == 0 and 0 or (math.log(math.abs(self.crankChange)) * C.CrankPower)
    self.crankLimited = math.abs(crankLimited)
end

---@return number batAngleDeg, number batSpeed
function UserInput:updateBat()
    local batAngleDeg = (playdate.getCrankPosition() + C.CrankOffsetDeg) % 360
    local batSpeed = self.crankLimited
    return batAngleDeg, batSpeed
end

function UserInput:runningSpeed()
    return self.crankLimited
end

---@param throwFlyMs number
---@param accuracy number | nil
---@return number | nil pitchFlyTimeMs, number | nil pitchTypeIndex, number | nil accuracy
local function userPitch(throwFlyMs, accuracy)
    local aPressed = playdate.buttonIsPressed(playdate.kButtonA)
    local bPressed = playdate.buttonIsPressed(playdate.kButtonB)
    if not aPressed and not bPressed then
        return throwFlyMs, 1, accuracy
    elseif aPressed and not bPressed then
        return throwFlyMs, 2, accuracy
    elseif not aPressed and bPressed then
        return throwFlyMs, 3, accuracy
    elseif aPressed and bPressed then
        return throwFlyMs, 4, accuracy
    end

    return nil, nil, nil
end

---@return number | nil pitchFlyTimeMs, number | nil pitchTypeIndex, number | nil accuracy
function UserInput:pitch()
    local powerRatio, accuracy = throwMeter:readThrow(self.crankChange)
    if powerRatio then
        local throwFly = C.PitchFlyMs / powerRatio
        if throwFly and not self.buttonControlledThrow(throwFly, true) then
            return userPitch(throwFly, accuracy)
        end
    end
end

function UserInput:fielderAction()
    local powerRatio = throwMeter:readThrow(self.crankChange)
    if powerRatio then
        local throwFly = C.PitchFlyMs / powerRatio
        if throwFly then
            self.buttonControlledThrow(throwFly, false)
        end
    end
end
