def has_applicable_environment(environment):
    """
    dict environment - very likely os.environ
    """
    return bool(
        all(
            key in environment
            for key in
            ["COMP_WORDS", "COMP_LENGTHS", "COMP_CWORD", "PCS_AUTO_COMPLETE"]
        )
        and
        environment['PCS_AUTO_COMPLETE'].strip() not in ('0', '')
        and
        environment['COMP_CWORD'].isdigit()
    )

def make_suggestions(environment, suggestion_tree):
    """
    dict environment - very likely os.environ
    dict suggestion_tree - {'acl': {'role': {'create': ...}}}...
    """
    if not has_applicable_environment(environment):
        raise EnvironmentError("Environment is not completion read")

    try:
        typed_word_list = _split_words(
            environment["COMP_WORDS"],
            environment["COMP_LENGTHS"].split(" "),
        )
    except EnvironmentError:
        return ""

    return "\n".join(_find_suggestions(
        suggestion_tree,
        typed_word_list,
        int(environment['COMP_CWORD'])
    ))

def _split_words(joined_words, word_lengths):
    cursor_position = 0
    words_string_len = len(joined_words)
    word_list = []
    for length in word_lengths:
        if not length.isdigit():
            raise EnvironmentError(
                "Length of word '{0}' is not digit".format(length)
            )
        next_position = cursor_position + int(length)
        if next_position > words_string_len:
            raise EnvironmentError(
                "Expected lengths are bigger than word lengths"
            )
        if(
            next_position != words_string_len
            and
            not joined_words[next_position].isspace()
        ):
            raise EnvironmentError("Words separator is not expected space")

        word_list.append(joined_words[cursor_position:next_position])
        cursor_position = next_position + 1

    if words_string_len > next_position:
        raise EnvironmentError("Expected lengths are smaller then word lengths")

    return word_list

def _find_suggestions(suggestion_tree, typed_word_list, word_under_cursor_idx):
    if not  1 <= word_under_cursor_idx <= len(typed_word_list):
        return []

    if len(typed_word_list) == word_under_cursor_idx:
        #not started type the last word yet
        word_under_cursor = ''
    else:
        word_under_cursor = typed_word_list[word_under_cursor_idx]

    words_for_current_cursor_position = _get_subcommands(
        suggestion_tree,
        typed_word_list[1:word_under_cursor_idx]
    )

    return [
        word for word in words_for_current_cursor_position
        if word.startswith(word_under_cursor)
    ]

def _get_subcommands(suggestion_tree, previous_subcommand_list):
    subcommand_tree = suggestion_tree
    for subcommand in previous_subcommand_list:
        if subcommand not in subcommand_tree:
            return []
        subcommand_tree = subcommand_tree[subcommand]
    return sorted(list(subcommand_tree.keys()))
