package com.khmelenko.lab.varis.presenter;

import android.text.TextUtils;

import com.khmelenko.lab.varis.common.Constants;
import com.khmelenko.lab.varis.mvp.MvpPresenter;
import com.khmelenko.lab.varis.network.response.Repo;
import com.khmelenko.lab.varis.network.response.User;
import com.khmelenko.lab.varis.network.retrofit.travis.TravisRestClientRx;
import com.khmelenko.lab.varis.storage.AppSettings;
import com.khmelenko.lab.varis.storage.CacheStorage;
import com.khmelenko.lab.varis.view.RepositoriesView;

import java.util.List;

import javax.inject.Inject;

import io.reactivex.SingleSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.BiConsumer;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

/**
 * Repositories presenter
 *
 * @author Dmytro Khmelenko (d.khmelenko@gmail.com)
 */
public class RepositoriesPresenter extends MvpPresenter<RepositoriesView> {

    private final TravisRestClientRx mTravisRestClient;
    private final CacheStorage mCache;

    private User mUser;

    private final CompositeDisposable mSubscriptions;

    @Inject
    public RepositoriesPresenter(TravisRestClientRx restClient, CacheStorage storage) {
        mTravisRestClient = restClient;
        mCache = storage;

        mSubscriptions = new CompositeDisposable();
    }

    @Override
    public void onAttach() {
        mUser = mCache.restoreUser();
        getView().updateMenuState(AppSettings.getAccessToken());
        getView().updateUserData(mUser);
        getView().showProgress();

        reloadRepos();
    }

    @Override
    public void onDetach() {
        getView().hideProgress();
        mSubscriptions.clear();
    }

    /**
     * Starts loading repositories
     */
    public void reloadRepos() {
        String accessToken = AppSettings.getAccessToken();
        if (TextUtils.isEmpty(accessToken)) {
            Disposable subscription = mTravisRestClient.getApiService()
                    .getRepos("")
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(reposHandler());

            mSubscriptions.add(subscription);
        } else {
            Disposable subscription = mTravisRestClient.getApiService()
                    .getUser()
                    .doOnSuccess(new Consumer<User>() {
                        @Override
                        public void accept(@NonNull User user) throws Exception {
                            cacheUserData(user);
                        }
                    })
                    .flatMap(new Function<User, SingleSource<List<Repo>>>() {
                        @Override
                        public SingleSource<List<Repo>> apply(@NonNull User user) throws Exception {
                            String loginName = mUser.getLogin();
                            return mTravisRestClient.getApiService().getUserRepos(loginName);
                        }
                    })
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(reposHandler());
            mSubscriptions.add(subscription);
        }
    }

    /**
     * Does user logout
     */
    public void userLogout() {
        mCache.deleteUser();
        mCache.deleteRepos();
        AppSettings.putAccessToken("");

        // reset back to open source url
        AppSettings.putServerUrl(Constants.OPEN_SOURCE_TRAVIS_URL);
        mTravisRestClient.updateTravisEndpoint(AppSettings.getServerUrl());
    }

    private BiConsumer<List<Repo>, Throwable> reposHandler() {
        return new BiConsumer<List<Repo>, Throwable>() {
            @Override
            public void accept(List<Repo> repos, Throwable throwable) throws Exception {
                if (mUser != null) {
                    getView().updateUserData(mUser);
                }

                if (throwable == null) {
                    handleReposLoaded(repos);
                } else {
                    handleLoadingFailed(throwable);
                }
            }
        };
    }

    private void cacheUserData(User user) {
        mUser = user;

        // cache user data
        mCache.saveUser(mUser);
    }

    private void handleReposLoaded(List<Repo> repos) {
        getView().hideProgress();
        getView().setRepos(repos);

        mCache.saveRepos(repos);
    }

    private void handleLoadingFailed(Throwable throwable) {
        getView().hideProgress();
        getView().showError(throwable.getMessage());
    }
}

@@ -839,48 +839,8 @@
 er;%0A
-import io.reactivex.functions.Consumer;%0A
 impo
@@ -2514,243 +2514,27 @@
 ess(
-new Consumer%3CUser%3E() %7B%0A                        @Override%0A                        public void accept(@NonNull User user) throws Exception %7B%0A                            cacheUserData(user);%0A                        %7D%0A                    %7D
+this::cacheUserData
 )%0A  
@@ -3621,158 +3621,29 @@
 urn 
-new BiConsumer%3CList%3CRepo%3E, Throwable%3E() %7B%0A            @Override%0A            public void accept(List%3CRepo%3E repos, Throwable throwable) throws Exception
+(repos, throwable) -%3E
  %7B%0A 
@@ -3649,28 +3649,24 @@
             
-  
-  
 if (mUser !=
@@ -3666,36 +3666,32 @@
 User != null) %7B%0A
-    
                 
@@ -3735,20 +3735,16 @@
         
-    
 %7D%0A%0A     
@@ -3746,28 +3746,24 @@
             
- 
-   
 if (throwabl
@@ -3767,36 +3767,32 @@
 able == null) %7B%0A
-    
                 
@@ -3817,20 +3817,16 @@
 repos);%0A
-    
         
@@ -3850,28 +3850,24 @@
             
-    
 handleLoadin
@@ -3886,34 +3886,16 @@
 wable);%0A
-                %7D%0A
         

Update RepositoriesPresenter to retrolambda