#!/usr/bin/env python3
from controlfloor import *

# You'd think the layout would look just like the camera roll layout, and it *is* similar, but
# there is a critical difference.  At the bottom of each image in "Recently Deleted" is a label
# with the number of remaining days until the file is automatically deleted.  The label is
# on top of an image which emulates a "transparent" background by cloning a chunk of the image
# beneath it (at least, this is what appears to be the case - the image is 24px tall, and the
# width of the image underneath). This makes a call to getElements(None,"image") return a bunch
# of extra stuff that must be filtered out.

def clear_recently_deleted_media():
    setDelay(0.5)
    launchApplication("com.apple.mobileslideshow")
    wait(3)

    albums_strings           = get_ios_strings("PhotosUI", "ALBUMS")
    recently_deleted_strings = get_ios_strings("PhotosUI", "ALL_TRASH_BIN")
    select_strings           = get_ios_strings("PhotosUI", "SELECT")
    more_strings             = get_ios_strings("PhotosUI", "MORE")
    delete_strings           = get_ios_strings("PhotosUI", "DELETE")
    delete_all_strings       = get_ios_strings("PhotosUI", "DELETE_ALL")
    no_photos_strings        = get_ios_strings("PhotosUI", "NO_PHOTOS_OR_VIDEOS")

    # iOS 16 will say "delete 17 videos?".  iOS 17 may say "Delete from this Device?"
    delete_n_items_matcher   = get_ios_string_matcher("PhotosUI", "DELETE_N_ITEMS")

    delete_all_strings += delete_strings #When selecting all photos, should be "ALL", unless only one photo remains...
    delete_from_device_this_device_strings = get_ios_strings("PhotosUI", "DELETE_FROM_THIS_DEVICE")

    if getNamedElements(no_photos_strings):
        return

    # iOS17 and older have a navbar on the bottom, and "Recently Deleted" is under the "Albums" section
    # on iOS18, you just swipe down for a while on the main page
    if getNamedElements(albums_strings, "navigationBar"):
        tap(albums_strings)

    if not getElements(recently_deleted_strings,"staticText", containsElementAtCenter=1):
        performGesture( "CenterSwipeUp" )
        wait(1)

    tap(recently_deleted_strings,"staticText")
    wait(1)

    buttons = getElements( select_strings, "button" )

    cancel_button = None

    while buttons:
        # See clear_camera_roll for comments on methodology below (nearly identical)
        buttons.get(select_strings, first=True).center.tap()
        wait(0.5)
        if not cancel_button:
            cancel_button = getElement(cancel_button,"button")

        pushDelay(0)
        tapped = {}
        # Note: in the element hierarchy, at the bottom of each image is a label, and each label
        # is on top of an image of the same size.  The image has no identifier, so we use getNamedElements
        # to ignore these.
        for e in getNamedElements( None, "image", matchesElementAtCenter = 1 ):
            if e.identifier == "PXPhotoViewGradient":
                continue
            if e.center in tapped: # Just in case, by chance, XCTest returns multiple overlapping elements
                continue
            tapped[e.center] = 1

            if e.maxY > 0.9 * deviceInfo.logicalHeight:
                continue
            if e.y < 0:
                continue
            if e.overlaps(cancel_button):
                continue
            e.point(0.75, 0.75).tap()
        popDelay()
        # iOS 17
        more_buttons = getElements( more_strings )
        if more_buttons:
            more_buttons[0].tap()
            wait(1)
        # iOS 16 does this without a sub menu. baffling...
        tap( delete_all_strings )
        wait(1)

        buttons = getNamedElements( None, "button" )
        delete_from_this_device_button = buttons.get( delete_from_device_this_device_strings, optional=True)
        if delete_from_this_device_button:
            delete_from_this_device_button.tap()
        else:
            for button in buttons:
                if delete_n_items_matcher.matches(button.id):
                     button.tap()
                break
            else:
                raise Exception("Could not find button to confirm delete")

        #tap( delete_from_device_this_device_strings )

        wait(1)

        no_photos_els = getElements( no_photos_strings )
        if no_photos_els:
            break

        buttons = getElements( select_strings, "button" )

cfrun(__name__, clear_recently_deleted_media)
