import re


def multi_replace(txt, find, repl, ignore_case=False, whole_word_only=False):
    """
    caastools.utils.multi_replace(text, repl, ignore_case=False, whole_word_only=False) -> str
    Performs simultaneous multi-replacement of substrings within a string
    :param txt: string in which replacements are to be performed
    :param find: sequence of strings for which replacments are to be made
    :param repl: sequence of strings with with to replace corresponding entry in find, or a function
    which achieves the same result
    which achieves the same
    :param ignore_case: specifies whether to ignore case in search/replacement. Default False
    :param whole_word_only: specifies whether to replace only on whole word matches. Default False
    :return: string with replacements made
    """

    repl_str = "{0}{{0}}{0}".format("\\b" if whole_word_only else '')

    # The problem is that there is the risk of having one replacement be
    # the substring of another. Deal with this issue by sorting long to short
    replacements = sorted(find, key=len, reverse=True)
    replace_re = re.compile("|".join(map(lambda x: repl_str.format(re.escape(x)), replacements)),
                            re.IGNORECASE if ignore_case else 0)

    if callable(repl):
        result = replace_re.sub(repl, txt)
    else:
        if len(repl) < len(find):
            raise ValueError("each entry in 'find' must have a corresponding entry in 'repl'")

        repl_dict = {f: r for f, r in zip(find, repl)}
        result = replace_re.sub(lambda match: repl_dict[match.group(0)], txt)

    return result