def insensitive_comparison(item1, item2, type_insensitive=False, string_insensitive=False):
    if not type_insensitive and type(item1) != type(item2):
        return False
    if isinstance(item1, Mapping):
        if not isinstance(item2, Mapping):
            return False
        if not len(item1) == len(item2):
            return False
        if not insensitive_comparison(list(item1.keys()), list(item2.keys()),
                                      type_insensitive=True):
            return False
        for key, val in item1.items():
            if not insensitive_comparison(item1[key], item2[key],
                                          type_insensitive=type_insensitive,
                                          string_insensitive=string_insensitive):
                return False
        return True
    elif isinstance(item1, str):
        if not isinstance(item2, str):
            return False
        if not len(item1) == len(item2) and not string_insensitive:
            return False
        if string_insensitive:
            if len(item1) <= 1:
                return item1.lower() == item2.lower()
            item1_list = [c for c in item1.lower() if not c.isspace()]
            item2_list = [c for c in item2.lower() if not c.isspace()]
            return insensitive_comparison(item1_list, item2_list,
                                          type_insensitive=type_insensitive,
                                          string_insensitive=string_insensitive)
        else:
            return item1 == item2
    elif isinstance(item1, Container) and isinstance(item1, Iterable):
        if not isinstance(item2, Container) or not isinstance(item2, Iterable):
            return False
        if not len(item1) == len(item2):
            return False
        item2_copy = list(deepcopy(item2))
        remove_failed = False
        for elem in item1:
            matched = False
            for candidate in item2:
                if insensitive_comparison(elem, candidate,
                                          type_insensitive=type_insensitive,
                                          string_insensitive=string_insensitive):
                    matched = True
                    try:
                        item2_copy.remove(candidate)
                    except ValueError:
                        remove_failed = True
                    break
            if not matched:
                return False
        if not remove_failed:
            return len(item2_copy) == 0
        else:
            for elem in item2:
                matched = False
                for candidate in item1:
                    if insensitive_comparison(elem, candidate,
                                              type_insensitive=type_insensitive,
                                              string_insensitive=string_insensitive):
                        matched = True
                        break
                if not matched:
                    return False
            return True
    else:
        return item1 == item2