package gregpearce.archivorg.domain.feed;

import com.google.auto.factory.AutoFactory;
import gregpearce.archivorg.domain.BasePresenter;
import gregpearce.archivorg.domain.model.FeedItem;
import gregpearce.archivorg.domain.model.ResultPage;
import gregpearce.archivorg.domain.network.FeedService;
import gregpearce.archivorg.util.RxDevUtil;
import gregpearce.archivorg.util.RxUtil;
import java.util.ArrayList;
import java.util.Collections;

@AutoFactory
public class FeedPresenter extends BasePresenter<FeedView, FeedViewState> {

  private FeedService feedService;

  private boolean fetchingNextPage = false;
  private boolean reachedBottomOfFeed = false;
  private int nextPageToFetch = 1;

  public FeedPresenter(FeedService feedService) {
    this.feedService = feedService;
  }

  @Override protected FeedViewState initViewState() {
    return FeedViewState.builder()
                        .showBottomLoading(false)
                        .showError(false)
                        .showRefreshing(true)
                        .showEmptyFeedMessage(false)
                        .feedItems(Collections.EMPTY_LIST)
                        .build();
  }

  @Override protected void start() {
    fetchPage();
  }

  private static final int LOAD_NEXT_PAGE_MARGIN = 10;

  public void scrolledToIndex(int index) {
    if (index > viewState.feedItems().size() - LOAD_NEXT_PAGE_MARGIN) {
      fetchPage();
    }
  }

  public void refresh() {
    reset();
    fetchPage();
  }

  public void retry() {
    updateViewState(viewState.toBuilder()
                             .showError(false)
                             .showBottomLoading(nextPageToFetch != 1)
                             .showRefreshing(nextPageToFetch == 1)
                             .build());
    fetchPage();
  }

  private void reset() {
    updateViewState(initViewState());
    fetchingNextPage = false;
    reachedBottomOfFeed = false;
    nextPageToFetch = 1;
  }

  private void fetchPage() {
    if (reachedBottomOfFeed || fetchingNextPage) {
      return;
    }
    fetchingNextPage = true;
    feedService.getPage(nextPageToFetch)
               .compose(RxUtil.subscribeDefaults())
               .subscribe(
                   result -> {
                     showPage(result);
                     fetchingNextPage = false;
                     nextPageToFetch++;
                   },
                   error -> {
                     showError();
                     fetchingNextPage = false;
                   });
  }

  private void showPage(ResultPage page) {
    reachedBottomOfFeed = page.isLastPage();
    boolean feedIsEmpty = reachedBottomOfFeed &&
                          viewState.feedItems().size() == 0 && page.results().size() == 0;
    // update presenter state
    ArrayList<FeedItem> feedItems =
        new ArrayList<>(viewState.feedItems().size() + page.results().size());
    feedItems.addAll(viewState.feedItems());
    feedItems.addAll(page.results());

    updateViewState(viewState.toBuilder()
                             .feedItems(feedItems)
                             .showBottomLoading(!reachedBottomOfFeed)
                             .showEmptyFeedMessage(feedIsEmpty)
                             .showRefreshing(false)
                             .build());
  }

  private void showError() {
    updateViewState(viewState.toBuilder()
                             .showError(true)
                             .showRefreshing(false)
                             .showBottomLoading(false)
                             .build());
  }
}
@@ -294,52 +294,8 @@
 ce;%0A
-import gregpearce.archivorg.util.RxDevUtil;%0A
 impo
@@ -388,16 +388,40 @@
 ections;
+%0Aimport rx.Subscription;
 %0A%0A@AutoF
@@ -554,40 +554,48 @@
 ate 
-boolean fetchingNextPage = false
+Subscription nextPageSubscription = null
 ;%0A  
@@ -1217,52 +1217,243 @@
 ate 
-static final int LOAD_NEXT_PAGE_MARGIN = 10;
+void reset() %7B%0A    if (nextPageSubscription != null) %7B%0A      nextPageSubscription.unsubscribe();%0A    %7D%0A    updateViewState(initViewState());%0A    nextPageSubscription = null;%0A    reachedBottomOfFeed = false;%0A    nextPageToFetch = 1;%0A  %7D
 %0A%0A  
@@ -1982,152 +1982,52 @@
 ate 
-void reset() %7B%0A    updateViewState(initViewState());%0A    fetchingNextPage = false;%0A    reachedBottomOfFeed = false;%0A    nextPageToFetch = 1;%0A  %7D
+static final int LOAD_NEXT_PAGE_MARGIN = 10;
 %0A%0A  
@@ -2084,32 +2084,44 @@
 Feed %7C%7C 
-fetchingNextPage
+nextPageSubscription != null
 ) %7B%0A    
@@ -2144,33 +2144,35 @@
     
-fetchingNextPage = true;%0A
+nextPageSubscription =%0A    
     
@@ -2223,16 +2223,20 @@
         
+   
+ 
 .compose
@@ -2264,16 +2264,20 @@
 ults())%0A
+    
         
@@ -2314,16 +2314,20 @@
         
+    
 result -
@@ -2347,24 +2347,28 @@
             
+ 
+   
 showPage(res
@@ -2398,34 +2398,45 @@
     
-fetchingNextPage = false;%0A
+    nextPageSubscription = null;%0A    
     
@@ -2494,11 +2494,19 @@
     
-%7D,%0A
+    %7D,%0A    
     
@@ -2548,24 +2548,28 @@
             
+ 
+   
 showError();
@@ -2594,34 +2594,45 @@
     
-fetchingNextPage = false;%0A
+    nextPageSubscription = null;%0A    
     
@@ -2887,37 +2887,8 @@
  0;%0A
-    // update presenter state
 %0A   

Refactor to cancel track current subscription and unsubscribe on refresh