// Path: app/src/main/java/br/ufs/demos/rxmvp/playground/core/behaviours/errors/UnexpectedResponseError.java
// public class UnexpectedResponseError extends RuntimeException {
// 
//     public UnexpectedResponseError(String message) {
//         super(message);
//     }
// 
// }
// 
// Path: app/src/main/java/br/ufs/demos/rxmvp/playground/core/behaviours/tooglerefresh/RefreshToogle.java
// public class RefreshToogle<T> implements FlowableTransformer<T, T> {
// 
//     private final ToogleRefreshView view;
//     private Scheduler targetScheduler;
// 
//     public RefreshToogle(ToogleRefreshView view, Scheduler targetScheduler) {
//         this.view = view;
//         this.targetScheduler = targetScheduler;
//     }
// 
//     @Override public Publisher<T> apply(Flowable<T> upstream) {
//         return upstream
//                 .doOnSubscribe(subscription -> fireAction(view.disableRefresh()))
//                 .doOnError(this::enableForSpecialErrorCase)
//                 .doOnComplete(() -> fireAction(view.enableRefresh()));
//     }
// 
//     private void enableForSpecialErrorCase(Throwable throwable) {
//         if (!(throwable instanceof UnexpectedResponseError)) fireAction(view.enableRefresh());
//     }
// 
//     private void fireAction(Action toPerform) {
//         Completable.fromAction(toPerform)
//                 .subscribeOn(targetScheduler)
//                 .subscribe();
//     }
// 
// }
// 
// Path: app/src/main/java/br/ufs/demos/rxmvp/playground/core/behaviours/tooglerefresh/ToogleRefreshView.java
// public interface ToogleRefreshView {
// 
//     Action disableRefresh();
// 
//     Action enableRefresh();
// 
// }
// 
// Path: app/src/test/java/br/ufs/demos/rxmvp/playground/util/MockitoHelpers.java
// public static VerificationMode oneTimeOnly() {
//     return VerificationModeFactory.times(1);
// }


import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import br.ufs.demos.rxmvp.playground.core.behaviours.errors.UnexpectedResponseError;
import br.ufs.demos.rxmvp.playground.core.behaviours.tooglerefresh.RefreshToogle;
import br.ufs.demos.rxmvp.playground.core.behaviours.tooglerefresh.ToogleRefreshView;
import io.reactivex.Flowable;
import io.reactivex.Scheduler;
import io.reactivex.functions.Action;
import io.reactivex.schedulers.Schedulers;
import static br.ufs.demos.rxmvp.playground.util.MockitoHelpers.oneTimeOnly;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
    @Test public void shouldEnableAfter_WhenNoSpecialError() throws Exception {
        Flowable<Integer> broken = Flowable.error(new RuntimeException("WTF!!"));

        broken.compose(toogler)
                .subscribe(
                        some -> {},
                        Throwable::printStackTrace,
                        () -> {}
                );

        checkForDisableFirstEnableAfter();
    }

    @Test public void shouldDisableAfter_WithSpecialError() throws Exception {
        Flowable<Integer> broken = Flowable.error(new UnexpectedResponseError("Server down"));

        broken.compose(toogler)
                .subscribe(
                        some -> {},
                        Throwable::printStackTrace,
                        () -> {}
                );

        checkForDisableFirstNotEnableAfter();

    }

    private void checkForDisableFirstEnableAfter() throws Exception {
        InOrder inOrder = inOrder(disableRefresh, enableRefresh);
        inOrder.verify(disableRefresh, oneTimeOnly()).run();
// Path: app/src/main/java/br/ufs/demos/rxmvp/playground/core/behaviours/errors/UnexpectedResponseError.java
// public class UnexpectedResponseError extends RuntimeException {
// 
//     public UnexpectedResponseError(String message) {
//         super(message);
//     }
// 
// }
// 
// Path: app/src/main/java/br/ufs/demos/rxmvp/playground/core/behaviours/tooglerefresh/RefreshToogle.java
// public class RefreshToogle<T> implements FlowableTransformer<T, T> {
// 
//     private final ToogleRefreshView view;
//     private Scheduler targetScheduler;
// 
//     public RefreshToogle(ToogleRefreshView view, Scheduler targetScheduler) {
//         this.view = view;
//         this.targetScheduler = targetScheduler;
//     }
// 
//     @Override public Publisher<T> apply(Flowable<T> upstream) {
//         return upstream
//                 .doOnSubscribe(subscription -> fireAction(view.disableRefresh()))
//                 .doOnError(this::enableForSpecialErrorCase)
//                 .doOnComplete(() -> fireAction(view.enableRefresh()));
//     }
// 
//     private void enableForSpecialErrorCase(Throwable throwable) {
//         if (!(throwable instanceof UnexpectedResponseError)) fireAction(view.enableRefresh());
//     }
// 
//     private void fireAction(Action toPerform) {
//         Completable.fromAction(toPerform)
//                 .subscribeOn(targetScheduler)
//                 .subscribe();
//     }
// 
// }
// 
// Path: app/src/main/java/br/ufs/demos/rxmvp/playground/core/behaviours/tooglerefresh/ToogleRefreshView.java
// public interface ToogleRefreshView {
// 
//     Action disableRefresh();
// 
//     Action enableRefresh();
// 
// }
// 
// Path: app/src/test/java/br/ufs/demos/rxmvp/playground/util/MockitoHelpers.java
// public static VerificationMode oneTimeOnly() {
//     return VerificationModeFactory.times(1);
// }


// Path: app/src/test/java/br/ufs/demos/rxmvp/playground/core/ToogleRefreshTests.java
import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import br.ufs.demos.rxmvp.playground.core.behaviours.errors.UnexpectedResponseError;
import br.ufs.demos.rxmvp.playground.core.behaviours.tooglerefresh.RefreshToogle;
import br.ufs.demos.rxmvp.playground.core.behaviours.tooglerefresh.ToogleRefreshView;
import io.reactivex.Flowable;
import io.reactivex.Scheduler;
import io.reactivex.functions.Action;
import io.reactivex.schedulers.Schedulers;
import static br.ufs.demos.rxmvp.playground.util.MockitoHelpers.oneTimeOnly;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;

    @Test public void shouldEnableAfter_WhenNoSpecialError() throws Exception {
        Flowable<Integer> broken = Flowable.error(new RuntimeException("WTF!!"));

        broken.compose(toogler)
                .subscribe(
                        some -> {},
                        Throwable::printStackTrace,
                        () -> {}
                );

        checkForDisableFirstEnableAfter();
    }

    @Test public void shouldDisableAfter_WithSpecialError() throws Exception {
        Flowable<Integer> broken = Flowable.error(new UnexpectedResponseError("Server down"));

        broken.compose(toogler)
                .subscribe(
                        some -> {},
                        Throwable::printStackTrace,
                        () -> {}
                );

        checkForDisableFirstNotEnableAfter();

    }

    private void checkForDisableFirstEnableAfter() throws Exception {
        InOrder inOrder = inOrder(disableRefresh, enableRefresh);
        inOrder.verify(disableRefresh, oneTimeOnly()).run();
        inOrder.verify(enableRefresh, oneTimeOnly()).run();