package com.lyft.scoop;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public abstract class Router {
private ScreenBackstack backStack = new ScreenBackstack();
private boolean allowEmptyStack;
public Router() {
this.allowEmptyStack = false;
}
public Router(boolean allowEmptyStack) {
this.allowEmptyStack = allowEmptyStack;
}
public boolean goBack() {
if (!backStack.isEmpty()) {
List<Screen> fromPath = backStack.asList();
backStack.pop();
performRouteChange(fromPath, backStack.asList(), TransitionDirection.EXIT);
if (!backStack.isEmpty() || allowEmptyStack) {
return true;
}
}
return false;
}
public void goTo(Screen nextScreen) {
if (tryHandleEmptyBackstack(nextScreen)) {
return;
}
List<Screen> fromPath = backStack.asList();
if (Screen.equals(backStack.peek(), nextScreen)) {
return;
}
backStack.push(nextScreen);
performRouteChange(fromPath, backStack.asList(), TransitionDirection.ENTER);
}
public void replaceWith(Screen nextScreen) {
if (tryHandleEmptyBackstack(nextScreen)) {
return;
}
List<Screen> fromPath = backStack.asList();
Screen previousScreen = backStack.peek();
if (Screen.equals(previousScreen, nextScreen)) {
return;
}
if (!backStack.isEmpty()) {
backStack.pop();
}
backStack.push(nextScreen);
performRouteChange(fromPath, backStack.asList(), TransitionDirection.ENTER);
}
public void replaceAllWith(Screen... screens) {
replaceAllWith(Arrays.asList(screens));
}
public void replaceAllWith(List<Screen> screens) {
List<Screen> fromPath = backStack.asList();
backStack.clear();
for (final Screen screen : screens) {
backStack.push(screen);
}
performRouteChange(fromPath, backStack.asList(), TransitionDirection.ENTER);
}
public void resetTo(Screen screen) {
if (tryHandleEmptyBackstack(screen)) {
return;
}
resetTo(screen, TransitionDirection.EXIT);
}
public void resetTo(Screen nextScreen, TransitionDirection direction) {
List<Screen> fromPath = backStack.asList();
// do nothing if screen already top of reset
if (!backStack.isEmpty() && Screen.equals(nextScreen, backStack.peek())) {
return;
}
while (!backStack.isEmpty()) {
Screen topScreen = backStack.peek();
if (Screen.equals(nextScreen, topScreen)) {
performRouteChange(fromPath, backStack.asList(), direction);
return;
}
backStack.pop();
}
backStack.push(nextScreen);
performRouteChange(fromPath, backStack.asList(), direction);
}
public boolean hasActiveScreen() {
return !backStack.isEmpty();
}
protected Screen peek() {
return backStack.peek();
}
private boolean tryHandleEmptyBackstack(final Screen screen) {
if (backStack.isEmpty()) {
backStack.push(screen);
performRouteChange(Collections.<Screen>emptyList(), backStack.asList(), TransitionDirection.ENTER);
return true;
}
return false;
}
private void performRouteChange(List<Screen> fromPath, List<Screen> toPath, TransitionDirection direction) {
onRouteChanged(new RouteChange(fromPath, toPath, direction));
}
protected abstract void onRouteChanged(RouteChange routeChange);
}