package com.lukekorth.deviceautomator;

import android.graphics.Rect;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;

import org.hamcrest.Matcher;
import org.hamcrest.StringDescription;

import static android.support.test.InstrumentationRegistry.getInstrumentation;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;

/**
 * A collection of assertions for use with {@link DeviceAutomator}.
 */
public abstract class AutomatorAssertion {

    /**
     * Asserts that the ui element specified in {@link DeviceAutomator#onDevice(UiObjectMatcher)}
     * is visible.
     *
     * @return
     */
    public static AutomatorAssertion visible(final boolean visible) {
        return new AutomatorAssertion() {
            @Override
            void wrappedCheck(UiObject object) throws UiObjectNotFoundException {
                try {
                    Rect bounds = object.getVisibleBounds();

                    if (bounds == null) {
                        fail("Matched view did not have any visible bounds");
                    }

                    if (visible) {
                        assertTrue("Matched view was not visible", bounds.width() > 0);
                        assertTrue("Matched view was not visible", bounds.height() > 0);
                    } else {
                        assertTrue("Matched view was visible", bounds.width() == 0);
                        assertTrue("Matched view was visible", bounds.height() == 0);
                    }
                } catch (UiObjectNotFoundException e) {
                    if (visible) {
                        fail(e.getMessage());
                    }
                }
            }
        };
    }

    /**
     * Asserts that the ui element specified in {@link DeviceAutomator#onDevice(UiObjectMatcher)}
     * has text that matches the given matcher.
     *
     * @param matcher The <a href="http://hamcrest.org/JavaHamcrest/">Hamcrest</a> to match against.
     * @return
     */
    public static AutomatorAssertion text(final Matcher matcher) {
        return new AutomatorAssertion() {
            @Override
            void wrappedCheck(UiObject object) throws UiObjectNotFoundException {
                visible(true).check(object);
                if (!matcher.matches(object.getText())) {
                    StringDescription description = new StringDescription();
                    description.appendText("Expected ");
                    matcher.describeTo(description);
                    description.appendText(" ");
                    matcher.describeMismatch(object.getText(), description);
                    assertTrue(description.toString(), false);
                }
            }
        };
    }

    /**
     * Asserts that the ui element specified in {@link DeviceAutomator#onDevice(UiObjectMatcher)}
     * has a content description that matches the given matcher.
     *
     * @param matcher The <a href="http://hamcrest.org/JavaHamcrest/">Hamcrest</a> to match against.
     * @return
     */
    public static AutomatorAssertion contentDescription(final Matcher matcher) {
        return new AutomatorAssertion() {
            @Override
            void wrappedCheck(UiObject object) throws UiObjectNotFoundException {
                visible(true).check(object);
                if (!matcher.matches(object.getContentDescription())) {
                    StringDescription description = new StringDescription();
                    description.appendText("Expected ");
                    matcher.describeTo(description);
                    description.appendText(" ");
                    matcher.describeMismatch(object.getText(), description);
                    assertTrue(description.toString(), false);
                }
            }
        };
    }

    /**
     * Asserts that the foreground app is the package specified.
     *
     * @param packageName The package to check for.
     * @return
     */
    public static AutomatorAssertion foregroundAppIs(final String packageName) {
        return new AutomatorAssertion() {
            @Override
            void wrappedCheck(UiObject object) throws UiObjectNotFoundException {
                assertTrue(UiDevice.getInstance(getInstrumentation()).hasObject(By.pkg(packageName)));
            }
        };
    }

    void check(UiObject object) {
        try {
            wrappedCheck(object);
        } catch (UiObjectNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    abstract void wrappedCheck(UiObject object) throws UiObjectNotFoundException;
}

@@ -929,32 +929,39 @@
 ide%0A            
+public 
 void wrappedChec
@@ -1006,32 +1006,32 @@
 oundException %7B%0A
-
                 
@@ -2304,32 +2304,39 @@
 ide%0A            
+public 
 void wrappedChec
@@ -3369,32 +3369,39 @@
 ide%0A            
+public 
 void wrappedChec
@@ -4305,24 +4305,31 @@
             
+public 
 void wrapped
@@ -4711,20 +4711,27 @@
 %0A    %7D%0A%0A
-
     
+public 
 abstract

Make AutomatorAssertion method public to allow custom assertions