package com.google.firebase.example.fireeats;

import android.content.Intent;
import android.support.test.espresso.ViewInteraction;
import android.support.test.espresso.contrib.RecyclerViewActions;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiSelector;
import android.support.test.uiautomator.UiScrollable;
import android.test.suitebuilder.annotation.LargeTest;
import android.view.accessibility.AccessibilityWindowInfo;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import com.google.firebase.auth.FirebaseAuth;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static android.support.test.InstrumentationRegistry.getInstrumentation;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withClassName;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.is;

@LargeTest @RunWith(AndroidJUnit4.class) public class MainActivityTest {

  @Rule public ActivityTestRule<MainActivity> mActivityTestRule =
      new ActivityTestRule<>(MainActivity.class, false, false);

  UiDevice device;
  final long TIMEOUT = 300000;  // Five minute timeout because our CI is slooow.

  @Before public void before() {
    // Sign out of any existing sessions
    FirebaseAuth.getInstance().signOut();
    device = UiDevice.getInstance(getInstrumentation());
  }

  @Test public void testAddItemsAndReview() throws Exception {
    mActivityTestRule.launchActivity(new Intent());

    // Input email for account created in the setup.sh
    getById("email").setText("test@mailinator.com");
    closeKeyboard();
    getById("button_next").clickAndWaitForNewWindow(TIMEOUT);

    //Input password
    getById("password").setText("password");
    closeKeyboard();
    getById("button_done").clickAndWaitForNewWindow(TIMEOUT);

    // Add random items
    openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext());
    ViewInteraction appCompatTextView = onView(
        allOf(withId(R.id.title), withText("Add Random Items"), childAtPosition(
            childAtPosition(withClassName(is("android.support.v7.view.menu.ListMenuItemView")), 0),
            0), isDisplayed()));
    appCompatTextView.perform(click());
    device.waitForIdle(TIMEOUT);

    // Click on the first restaurant
    getById("recycler_restaurants").getChild(new UiSelector().index(0))
        .clickAndWaitForNewWindow(TIMEOUT);

    // Click add review
    getById("fab_show_rating_dialog").click();

    //Write a review
    getById("restaurant_form_text").setText("\uD83D\uDE0E\uD83D\uDE00");
    closeKeyboard();

    //Submit the review
    getById("restaurant_form_button").clickAndWaitForNewWindow(TIMEOUT);

    // Assert that the review exists
    UiScrollable ratingsList = new UiScrollable(getIdSelector("recycler_ratings"));
    ratingsList.waitForExists(TIMEOUT);
    ratingsList.scrollToBeginning(100);
    Assert.assertTrue(
        getById("recycler_ratings")
            .getChild(new UiSelector().text("\uD83D\uDE0E\uD83D\uDE00"))
            .waitForExists(TIMEOUT));
  }

  private UiObject getById(String id) {
    UiObject obj = device.findObject(getIdSelector(id));
    obj.waitForExists(TIMEOUT);
    return obj;
  }

  private UiSelector getIdSelector(String id) {
    return new UiSelector().resourceId("com.google.firebase.example.fireeats:id/" + id);
  }

  private void closeKeyboard() {
    for (AccessibilityWindowInfo w : getInstrumentation().getUiAutomation().getWindows()) {
      if (w.getType() == AccessibilityWindowInfo.TYPE_INPUT_METHOD) {
        device.pressBack();
        return;
      }
    }
  }

  private static Matcher<View> childAtPosition(final Matcher<View> parentMatcher,
      final int position) {

    return new TypeSafeMatcher<View>() {
      @Override public void describeTo(Description description) {
        description.appendText("Child at position " + position + " in parent ");
        parentMatcher.describeTo(description);
      }

      @Override public boolean matchesSafely(View view) {
        ViewParent parent = view.getParent();
        return parent instanceof ViewGroup && parentMatcher.matches(parent) && view.equals(
            ((ViewGroup) parent).getChildAt(position));
      }
    };
  }
}

@@ -75,128 +75,8 @@
 nt;%0A
-import android.support.test.espresso.ViewInteraction;%0Aimport android.support.test.espresso.contrib.RecyclerViewActions;%0A
 impo
@@ -503,233 +503,45 @@
 ort 
-android.view.View;%0Aimport android.view.ViewGroup;%0Aimport android.view.ViewParent;%0Aimport com.google.firebase.auth.FirebaseAuth;%0Aimport org.hamcrest.Description;%0Aimport org.hamcrest.Matcher;%0Aimport org.hamcrest.TypeSafeMatcher
+com.google.firebase.auth.FirebaseAuth
 ;%0Aim
@@ -751,69 +751,8 @@
 on;%0A
-import static android.support.test.espresso.Espresso.onView;%0A
 impo
@@ -839,625 +839,8 @@
 enu;
-%0Aimport static android.support.test.espresso.action.ViewActions.click;%0Aimport static android.support.test.espresso.assertion.ViewAssertions.matches;%0Aimport static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;%0Aimport static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;%0Aimport static android.support.test.espresso.matcher.ViewMatchers.withClassName;%0Aimport static android.support.test.espresso.matcher.ViewMatchers.withId;%0Aimport static android.support.test.espresso.matcher.ViewMatchers.withText;%0Aimport static org.hamcrest.Matchers.allOf;%0Aimport static org.hamcrest.Matchers.is;
 %0A%0A@L
@@ -1892,304 +1892,155 @@
     
-ViewInteraction appCompatTextView = onView(%0A        allOf(withId(R.id.title), withText(%22Add Random Items%22), childAtPosition(%0A            childAtPosition(withClassName(is(%22android.support.v7.view.menu.ListMenuItemView%22)), 0),%0A            0), isDisplayed()));%0A    appCompatTextView.perform(
+UiObject addItems = device.findObject(new UiSelector().textContains(%22Add Random Items%22));%0A    addItems.waitForExists(TIMEOUT);%0A    addItems.
 click()
-)
 ;%0A  
@@ -3439,634 +3439,7 @@
 %0A  %7D
-%0A%0A  private static Matcher%3CView%3E childAtPosition(final Matcher%3CView%3E parentMatcher,%0A      final int position) %7B%0A%0A    return new TypeSafeMatcher%3CView%3E() %7B%0A      @Override public void describeTo(Description description) %7B%0A        description.appendText(%22Child at position %22 + position + %22 in parent %22);%0A        parentMatcher.describeTo(description);%0A      %7D%0A%0A      @Override public boolean matchesSafely(View view) %7B%0A        ViewParent parent = view.getParent();%0A        return parent instanceof ViewGroup && parentMatcher.matches(parent) && view.equals(%0A            ((ViewGroup) parent).getChildAt(position));%0A      %7D%0A    %7D;%0A  %7D
 %0A%7D%0A

Rewrite ActionBar interactions in UIAutomator.