def pad_sequence(
        seq:str,
        max_seq_len:int,
        pad_value:str="J",
        align:str="end") -> str:
    """ Pad `seq` to `max_seq_len` with `value` based on the `align` strategy

    If `seq` is already of length `max_seq_len` *or longer* it will not be
    changed.

    Parameters
    ----------
    seq : str
        The character sequence

    max_seq_len : int
        The maximum length for a sequence

    pad_value : str
        The value for padding. This should be a single character

    align : str
        The strategy for padding the string. Valid options are `start`, `end`,
        and `center`

    Returns
    -------
    padded_seq : str
        The padded string. In case `seq` was already long enough or longer, it
        will not be changed. So `padded_seq` could be longer than `max_seq_len`.
    """
    seq_len = len(seq)
    assert max_seq_len >= seq_len
    if align == "end":
        n_left = max_seq_len - seq_len
        n_right = 0
    elif align == "start":
        n_right = max_seq_len - seq_len
        n_left = 0
    elif align == "center":
        n_left = (max_seq_len - seq_len) // 2 + (max_seq_len - seq_len) % 2
        n_right = (max_seq_len - seq_len) // 2
    else:
        raise ValueError("align can be of: end, start or center")

    # normalize for the length
    n_left = n_left // len(pad_value)
    n_right = n_right // len(pad_value)

    return pad_value * n_left + seq + pad_value * n_right