package com.kickstarter.presenters;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Pair;
import android.widget.Toast;

import com.kickstarter.KSApplication;
import com.kickstarter.libs.CurrentUser;
import com.kickstarter.libs.Presenter;
import com.kickstarter.libs.RxUtils;
import com.kickstarter.models.Comment;
import com.kickstarter.models.Project;
import com.kickstarter.models.User;
import com.kickstarter.services.ApiClient;
import com.kickstarter.services.apiresponses.CommentsEnvelope;
import com.kickstarter.ui.activities.CommentFeedActivity;
import com.kickstarter.ui.adapters.CommentFeedAdapter;
import com.kickstarter.ui.viewholders.EmptyCommentFeedViewHolder;

import java.util.Arrays;
import java.util.List;

import javax.inject.Inject;

import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.subjects.PublishSubject;
import timber.log.Timber;

public class CommentFeedPresenter extends Presenter<CommentFeedActivity> implements CommentFeedAdapter.Delegate {
  private final PublishSubject<Void> contextClick = PublishSubject.create();
  private final PublishSubject<Void> loginClick = PublishSubject.create();
  private final PublishSubject<Void> loginSuccess = PublishSubject.create();
  private final PublishSubject<Void> postSuccess = PublishSubject.create();

  @Inject ApiClient client;
  @Inject CurrentUser currentUser;

  @Override
  protected void onCreate(@NonNull final Context context, @Nullable final Bundle savedInstanceState) {
    super.onCreate(context, savedInstanceState);
    ((KSApplication) context.getApplicationContext()).component().inject(this);
  }

  // todo: add pagination to comments
  public void initialize(@NonNull final Project initialProject) {

    final Observable<Project> project = loginSuccess.flatMap(__ -> client.fetchProject(initialProject))
      .startWith(initialProject);

    final Observable<List<Comment>> comments = client.fetchProjectComments(initialProject)
      .map(CommentsEnvelope::comments);

    // todo: merge on post success. test this.------>
    final Observable<List<Comment>> commentsOnPostSuccess = postSuccess
      .take(1)
      .flatMap(__ -> client.fetchProjectComments(initialProject))
      .map(CommentsEnvelope::comments)
      .mergeWith(comments);

    final Observable<List<?>> viewCommentsProject = Observable.combineLatest(
      Arrays.asList(viewSubject, commentsOnPostSuccess, project),
      Arrays::asList);

    final Observable<Pair<CommentFeedActivity, Project>> viewAndProject =
      RxUtils.combineLatestPair(viewSubject, project);

    // logged in user == backer --> post comment
    addSubscription(RxUtils.combineLatestPair(viewAndProject, loginSuccess)
      .filter(vpl -> vpl.first.second.isBacking())
      .take(1)
      .map(vpl -> vpl.first.first)
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(CommentFeedActivity::showCommentDialog)
    );

    addSubscription(RxUtils.takePairWhen(currentUser.observable(), viewCommentsProject)
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(uvcp -> {
        final User u = uvcp.first;
        final CommentFeedActivity view = (CommentFeedActivity) uvcp.second.get(0);
        final List<Comment> cs = (List<Comment>) uvcp.second.get(1);
        final Project p = (Project) uvcp.second.get(2);
        view.show(p, cs, u);
      }));

    addSubscription(RxUtils.takeWhen(viewSubject, contextClick)
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(CommentFeedActivity::onBackPressed));

    addSubscription(RxUtils.takeWhen(viewSubject, loginClick)
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(CommentFeedActivity::commentFeedLogin));
  }

  public void emptyCommentFeedLoginClicked(@NonNull final EmptyCommentFeedViewHolder viewHolder) {
    loginClick.onNext(null);
  }

  public void postCommentOnClick(@NonNull final Project project, @NonNull final String body) {
    Timber.d(body);
    postSuccess.onNext(null);

    client.postProjectComment(project, body)
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(this::showToastOnSuccess);
  }

  private void showToastOnSuccess(@Nullable final Comment comment) {
    final String message = (comment == null) ? "Comment could not be posted" : "Comment posted!";
    final Toast toast = Toast.makeText(view().getApplicationContext(), message, Toast.LENGTH_LONG);
    toast.show();
    postSuccess.onNext(null);
  }

//  private void error(final Throwable e) {
//    if (!hasView()) {
//      return;
//    }
//
//    // check: network error
//    new ApiErrorHandler(e, view()) {
//      @Override
//      public void handleApiError(final ApiError apiError) {
//        switch (apiError.errorEnvelope().ksrCode()) {
//          default:
//            displayError(-1);
//            break;
//        }
//      }
//    }.handleError();
//  }

  public void projectContextClicked() {
    contextClick.onNext(null);
  }

  public void takeLoginSuccess() {
    loginSuccess.onNext(null);
  }
}

@@ -4057,16 +4057,18 @@
 (body);%0A
+//
     post
@@ -4094,16 +4094,32 @@
 );%0A%0A    
+addSubscription(
 client.p
@@ -4224,33 +4224,41 @@
 (this::s
-howToastOnSuccess
+uccess, this::error)%0A    
 );%0A  %7D%0A%0A
@@ -4277,19 +4277,8 @@
 id s
-howToastOnS
 ucce
@@ -4566,18 +4566,16 @@
 );%0A  %7D%0A%0A
-//
   privat
@@ -4583,24 +4583,33 @@
  void error(
+@NonNull 
 final Throwa
@@ -4621,385 +4621,52 @@
 ) %7B%0A
-//
     
-if (!hasView()) %7B%0A//      return;%0A//    %7D%0A//%0A//    // check: network error%0A//    new ApiErrorHandler(e, view()) %7B%0A//      @Override%0A//      public void handleApiError(final ApiError apiError) %7B%0A//        switch (apiError.errorEnvelope().ksrCode()) %7B%0A//          default:%0A//            displayError(-1);%0A//            break;%0A//        %7D%0A//      %7D%0A//    %7D.handleError();%0A//
+// todo: handle 422s and network errors%0A
   %7D%0A

mark error handling todo