mutable struct FPGroupIter{S, T, GEl}
    seen::S
    seen_iter_state::T
    current::GEl
    gen_idx::Int
    u_tmp::GEl
    v_tmp::GEl
end

function Base.iterate(G::AbstractFPGroup)
    seen = OrderedSet([one(G)])
    current, seen_state = iterate(seen)
    gr_iter = FPGroupIter(seen, seen_state, current, 1, one(G), one(G))
    return one(G), gr_iter
end

function _next_elt!(itr::FPGroupIter)
    res = iterate(itr.seen, itr.seen_iter_state)
    res === nothing && return true

    itr.current = first(res)
    itr.seen_iter_state = last(res)
    itr.gen_idx = 1

    return false
end

function Base.iterate(G::AbstractFPGroup, state)
    if state.gen_idx > length(alphabet(G))
        finished = _next_elt!(state)
        finished && return nothing
    end

    elt = let u = state.u_tmp, v = state.v_tmp, current = state.current
        copyto!(v, current)
        push!(word(v), state.gen_idx)
        _setnormalform!(v, false)
        _setvalidhash!(v, false)
        @assert !isnormalform(v)

        resize!(word(u), 0)
        normalform!(u, v)
    end

    state.gen_idx += 1

    if elt in state.seen
        return iterate(G, state)
    else
        @assert isnormalform(elt)
        push!(state.seen, deepcopy(elt))
        return elt, state
    end
end

# Groups.Core default:
# Base.IteratorSize(::Type{<:AbstractFPGroup}) = Base.SizeUnknown()
