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

def clear_camera_roll():
    launchApplication("com.apple.mobileslideshow")
    wait(2)

    library_strings     = get_ios_strings("PhotosUI", "LIBRARY")    # Library / Photos
    continue_strings    = get_ios_strings("PhotosUI", "CONTINUE")   # Continue
    select_strings      = get_ios_strings("PhotosUI", "SELECT")     # Select
    open_camera_strings = get_ios_strings("PhotosUI", "EMPTY_PHOTO_LIBRARY_OPEN_CAMERA") # Open Camera
    delete_strings      = get_ios_strings("PhotosUI", "DELETE")     # Delete / Delete Item
    cancel_strings      = get_ios_strings("PhotosUI", "CANCEL")     # Cancel
    all_photos_strings  = get_ios_strings("PhotosUI", "ALL_PHOTOS") # All Photos
    no_photos_strings   = get_ios_strings("PhotosUI", "NO_PHOTOS_OR_VIDEOS") # No Photos or Videos

    buttons = getElements(None, "button")

    # Dismiss anything that might pop up, work towards standard all-photos displaye
    retries = 4
    retry   = 0
    all_photos_button_tapped = 0
    while 1:
        # print("trying" + str(retry))
        retry += 1

        # One-time prompt #1:
        if continue_button := buttons.get(continue_strings, exceptions=0):
            # This may be followed by an alert to accept privacy terms & conditions
            # We are not automating this for the moment.  If the alert is displayed
            # and no rule has been written to dismiss it, this function will fail,
            # which is what we want.
            continue_button.tap()
        elif (not all_photos_button_tapped) and buttons.contains(all_photos_strings):
            all_photos_button = buttons.get(all_photos_strings, exceptions=0)
            # If you have older photos, the photo view will open to a rollup view with a
            # Years/Months/Days/All Photos  filter.  Need to switch to "All Photos" to get
            # the expected UI.
            all_photos_button.tap()
            all_photos_button_tapped = 1
        elif buttons.contains(select_strings + open_camera_strings):
            # This is what we're looking for, but we might have needed to tap "All Photos" once (above)
            break
        elif library_button := buttons.get(library_strings, exceptions=0):
            # If not already viewing library, need to switch to library view.
            library_button.tap()
        else:
            print(repr(buttons))
            raise Exception("Could not find expected buttons. Retry %d of %d-1" % (retry, retries))

        wait(2)
        if retry >= retries:
            print(repr(buttons))
            raise Exception("Could not find expected buttons. Retry %d of %d-2" % (retry, retries))

        buttons = getElements(None, "button")

    wait(2)

    cancel_button = None

    # Note: as you repeat this loop, it appears that the app destroys and recreates *multiple*
    # "select" buttons.  Sometimes one appears with the identifier "PXCuratedLibraryOverlayButton_AX",
    # but not the first time the screen is displayed.  Mysterious.
    while buttons.contains(select_strings) and not buttons.contains(open_camera_strings):
        buttons.get(select_strings, first=True).center.tap()
        wait(0.5)
        if not cancel_button:
            cancel_button = getElement(cancel_button,"button")

        pushDelay(0)
        # The images have labels, but the labels are not necessarily unique.  One label format,
        # for instance, is:
        #     Live Photo, December 22, 1:44
        # which is shared by all photos taken within the same minute.  Likewise, files downloaded
        # from the internet with the same name, or cloned from each other, might have identical
        # labels.
        # Moreover, some things about XCTest...
        # If you ask XCTest to tap an element via the API, it will scroll an offscreen element
        # onscreen automatically (usually) which can be quite handy.  But it will *not* scroll
        # an element out of the way of another element that is on top of it.  When selecting
        # multiple images, there is a small "cancel" button in the top-right corner that is
        # *on top* of the images, and if you "tap" an image that is either in that location,
        # or scrolled into that location, XCTest will inadvertently tap the cancel button.
        #
        # We can exclude items in various ways.  We'll just be conservative about which images
        # we tap, and just cycle till everything is deleted.
        count = 0
        for e in getElements( None, "image" ):
            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()
            count += 1
        popDelay()

        if count == 0:
            # There are no files, iOS 18+
            if getElements(open_camera_strings) and getElements(no_photos_strings,"staticText"):
                return

        tap( delete_strings )

        for e in getElements( None, "button" ):
            if text_matches_ios_string( e.label, "PhotosUI", "DELETE_N_ITEMS" ):
                tap( e.label ) #e.tapcenter.tap()
                break
        else:
            raise Exception( "Couldn't find button to confirm delete. " )

        wait(1)

        onetime_strings = get_ios_strings("PhotosUI", "DELETE_ONETIME_TITLE")  # Deleted Photos Are Moved to the Recently Deleted Album
        ok_strings = get_ios_strings("UIKit", "OK")
        if getElements(onetime_strings):
            tap( ok_strings )
            wait(2)

        centerSwipeDown()
        wait(2)
        buttons = getElements( select_strings + open_camera_strings, "button" )

    # When there are no photos, we should get an "Open Camera" link
    if not buttons.contains(open_camera_strings):
        raise Exception("Failed to clear photos")

cfrun(__name__, clear_camera_roll)
