import random
import string
import shortuuid


def gen_n_digit_string(n):
    numbers = string.digits
    return ''.join(random.SystemRandom().choice(numbers) for _ in range(n))


def generate_initials(name, max_initials=2):
    """
    Generates initials for a person's or organization's name.

    Name can be a string or list. If inputted as a list, input names in desired order of
    initials, such as [first, last]. If an element of that list has multiple names
    (e.g. a middle name or multiple last names), those names will also be taken into account.
    """
    if not name:
        return None

    if isinstance(name, str):
        name_split = name.split(' ', max(max_initials - 1, -1))
        name_split.insert(0, '_recursive')
        initials = generate_initials(name_split, max_initials)
    elif isinstance(name, list):
        if name[0] == '_recursive':
            del name[0]
        else:
            name = ' '.join(name).split(' ', max(max_initials - 1, -1))

        if len(name) > 1:
            initials = name.pop(0)[0]
            s_n = name.pop(-1)[0]
            name_count = 2

            if initials:
                for s in name:
                    if name_count < max_initials - 1:
                        initials += s[0]
                        name_count += 1
                    else:
                        break

            if name_count <= max_initials:
                initials += s_n
        else:
            initials = name[0][0]

        initials = initials.upper()
    else:
        raise Exception("Name must be a string or a list of strings.")

    return initials


def password_gen(string_length=16):
    mixup = string.ascii_letters + string.digits
    return ''.join(random.choice(mixup) for _ in range(string_length))


def shorter_uuid(length=7, starter=None, with_original=False):
    """
    Generate an even shorter short UUID generated by the shortuuid library.

    :param length: Length of trimmed ID.
    :param starter: Whether to begin with an already-created ShortUUID.
                    Useful when using recursively.
    :param with_original: Also return initially-generated ShortUUID
    :return:
    """
    original_id = str(shortuuid.uuid()) if starter is None else starter
    n = len(original_id)
    dx = min(length, len(original_id))  # ID length
    if starter is not None and len(starter) < dx * 2:
        original_id = str(shortuuid.uuid())

    start_point = random.randint(0, n - dx)
    shorter_id = original_id[start_point:(start_point + dx)]

    return shorter_id if not with_original else [shorter_id, original_id]
