def merge_sort(collection):
    """
    Counts the number of comparisons (between two elements) and swaps
    between elements while performing a merge sort

    :param collection: a collection of comparable elements
    :return: total number of comparisons and swaps, and the sorted list
    """
    comparisons, swaps = 0, 0
    mid = len(collection) // 2
    left, right = collection[:mid], collection[mid:]

    if len(left) > 1:
        left_result = merge_sort(left)
        comparisons += left_result[0]
        swaps += left_result[1]
        left = left_result[2]
    if len(right) > 1:
        right_result = merge_sort(right)
        comparisons += right_result[0]
        swaps += right_result[1]
        right = right_result[2]

    sorted_collection = list()

    # while elements in both sub lists
    while left and right:
        if left[0] <= right[0]:
            sorted_collection.append(left.pop(0))
        else:
            sorted_collection.append(right.pop(0))
        comparisons, swaps = comparisons + 1, swaps + 1

    # if elements are left in only one sublist, merge them (guaranteed sorted)
    # this does not count as swapping as it is just a copy operation
    #  no need for swap += len(left or right)
    sorted_collection += (left or right)

    return comparisons, swaps, sorted_collection