import itertools
import string
import time


def event_num(counter=None):
    """Generate an approximately-unique numeric identifier.

    Integer result is generated from the current epoch time in
    nanoseconds and a complementary arbitrary number to help avoid sub-
    nanosecond collision. (Note that the arbitrary complement is
    generated via counter, not randomly, to further approximate
    uniqueness.)

    This is intended to provide relatively *short* and inexpensively-
    computed unique identifiers within a single context (*e.g.* for a
    single host and application). See event_id().

    """
    time_ = time.time_ns()
    count = next(event_num.counter if counter is None else counter)
    return 100 * time_ + count


def make_cyclic_counter(size=100):
    return itertools.cycle(range(size))

event_num.counter = make_cyclic_counter()

event_num.make_cyclic_counter = make_cyclic_counter


def int_to_id(num, alphabet=(string.digits + string.ascii_letters)):
    """Translate a given integer to the base of a given alphabet."""
    if num == 0:
        return alphabet[0]

    base = len(alphabet)

    result = ''

    while num:
        (num, pos) = divmod(num, base)
        char = alphabet[pos]
        result = char + result

    return result


def event_id(counter=None):
    """Generate an approximately-unique alphanumeric identifier.

    This is intended to provide relatively *short* and inexpensively-
    computed unique identifiers within a single context (*e.g.* for a
    single host and application). See event_num().

    (Note that performance is impacted by Python implementation and
    considered in comparison to approximate alternatives including uuid,
    hashlib and/or random. This utility is intended to compute
    approximately-unique identifiers, shorter in string length than
    those generated by uuid and hashlib, and with comparable
    performance.)

    """
    return int_to_id(event_num(counter))
