package flow.sample.basic;

import android.content.res.Configuration;
import android.support.test.InstrumentationRegistry;
import android.support.test.espresso.action.ViewActions;
import android.support.test.rule.ActivityTestRule;
import org.junit.Rule;
import org.junit.Test;

import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.Espresso.pressBack;
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.isAssignableFrom;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;

/**
 * Verifies that simple navigation works, along with Flow and view state persistence across
 * navigation and across configuration changes.
 */
public class BasicSampleTest {

  @Rule public ActivityTestRule rule = new ActivityTestRule<>(BasicSampleActivity.class);

  /** Verifies that the app is in its default state on a cold start. */
  @Test public void defaultKeyIsUsed() {
    onView(withId(R.id.basic_activity_frame))
        .check(matches(hasDescendant(isAssignableFrom(WelcomeView.class))));
  }

  /**
   * Verifies that the current Flow state is maintained, as well as view state associated with
   * Flow state.
   */
  @Test public void rotationMaintainsState() {

    // Enter some text on the welcome screen
    onView(withId(R.id.welcome_screen_name))
        .perform(ViewActions.typeText("Bart"));

    rotate();

    // We should still have that text, despite the configuration change.
    onView(withId(R.id.welcome_screen_name))
        .check(matches(withText("Bart")));

    // Continue to the next screen and verify that it's showing info from our Flow state object.
    onView(withId(R.id.welcome_screen_name))
        .perform(ViewActions.typeText("\n"));
    onView(withId(R.id.hello_name))
        .check(matches(withText("Hello Bart")));

    // Change the text in the counter TextView. Only this view knows its state, we don't store it
    // anywhere else.
    onView(withId(R.id.hello_increment))
        .perform(click())
        .perform(click());
    onView(withId(R.id.hello_counter))
        .check(matches(withText("2")));

    rotate();

    // Verify that we still have our Flow state object.
    onView(withId(R.id.hello_name))
        .check(matches(withText("Hello Bart")));
    // Verify that the counter TextView's view state was restored.
    onView(withId(R.id.hello_counter))
        .check(matches(withText("2")));
  }

  /** Verifies that states in the history keep their associated view state. */
  @Test public void goingBackWorksAndRestoresState() {

    // Enter some text in the name field and go forward.
    // The field's view state, including the text we entered, should be remembered in the history.
    onView(withId(R.id.welcome_screen_name))
        .perform(ViewActions.typeText("Bart\n"));
    onView(withId(R.id.basic_activity_frame))
        .check(matches(hasDescendant(isAssignableFrom(HelloView.class))));

    pressBack();

    onView(withId(R.id.basic_activity_frame))
        .check(matches(hasDescendant(isAssignableFrom(WelcomeView.class))));

    // When we navigated back, the view state of the name field should have been restored.
    onView(withId(R.id.welcome_screen_name))
        .check(matches(withText("Bart")));
  }

  private void rotate() {
    Configuration config =
        InstrumentationRegistry.getTargetContext().getResources().getConfiguration();
    rule.getActivity().setRequestedOrientation(
        (config.orientation == ORIENTATION_PORTRAIT) ?
            SCREEN_ORIENTATION_LANDSCAPE : SCREEN_ORIENTATION_PORTRAIT);
  }
}