package com.tehmou.rxbookapp.data;

import com.tehmou.rxbookapp.data.provider.UserSettingsContract;
import com.tehmou.rxbookapp.data.stores.GitHubRepositorySearchStore;
import com.tehmou.rxbookapp.data.stores.GitHubRepositoryStore;
import com.tehmou.rxbookapp.data.stores.UserSettingsStore;
import com.tehmou.rxbookapp.network.NetworkApi;
import com.tehmou.rxbookapp.pojo.GitHubRepository;
import com.tehmou.rxbookapp.pojo.GitHubRepositorySearch;
import com.tehmou.rxbookapp.pojo.UserSettings;

import android.content.ContentResolver;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import rx.Observable;
import rx.schedulers.Schedulers;


/**
 * Created by ttuo on 19/03/14.
 */
public class DataLayer {
    private final NetworkApi networkApi;
    private final GitHubRepositoryStore gitHubRepositoryStore;
    private final GitHubRepositorySearchStore gitHubRepositorySearchStore;
    private final UserSettingsStore userSettingsStore;

    public DataLayer(ContentResolver contentResolver) {
        networkApi = new NetworkApi();
        gitHubRepositoryStore = new GitHubRepositoryStore(contentResolver);
        gitHubRepositorySearchStore = new GitHubRepositorySearchStore(contentResolver);
        userSettingsStore = new UserSettingsStore(contentResolver);
    }

    public Observable<GitHubRepositorySearch> getGitHubRepositorySearch(final String search) {
        Observable.<List<GitHubRepository>>create((subscriber) -> {
                    try {
                        Map<String, String> params = new HashMap<>();
                        params.put("q", search);
                        List<GitHubRepository> results = networkApi.search(params);
                        subscriber.onNext(results);
                        subscriber.onCompleted();
                    } catch (Exception e) {
                        subscriber.onError(e);
                    }
                })
                .subscribeOn(Schedulers.computation())
                .map((repositories) -> {
                    final List<Integer> repositoryIds = new ArrayList<>();
                    for (GitHubRepository repository : repositories) {
                        gitHubRepositoryStore.put(repository);
                        repositoryIds.add(repository.getId());
                    }
                    return new GitHubRepositorySearch(search, repositoryIds);
                })
                .subscribe(gitHubRepositorySearchStore::put);
        return gitHubRepositorySearchStore.getStream(search);
    }

    public Observable<GitHubRepository> getGitHubRepository(Integer repositoryId) {
        return gitHubRepositoryStore.getStream(repositoryId);
    }

    public Observable<GitHubRepository> fetchAndGetGitHubRepository(Integer repositoryId) {
        fetchGitHubRepository(repositoryId);
        return getGitHubRepository(repositoryId);
    }

    private void fetchGitHubRepository(Integer repositoryId) {
        Observable.<GitHubRepository>create(subscriber -> {
                    try {
                        GitHubRepository repository = networkApi.getRepository(repositoryId);
                        subscriber.onNext(repository);
                        subscriber.onCompleted();
                    } catch (Exception e) {
                        subscriber.onError(e);
                    }
                })
                .subscribeOn(Schedulers.computation())
                .subscribe(gitHubRepositoryStore::put);
    }

    public Observable<UserSettings> getUserSettings() {
        return userSettingsStore.getStream(UserSettingsContract.DEFAULT_USER_ID);
    }

    public void setUserSettings(UserSettings userSettings) {
        userSettingsStore.insertOrUpdate(userSettings);
    }

    public static interface GetUserSettings {
        Observable<UserSettings> call();
    }

    public static interface SetUserSettings {
        void call(UserSettings userSettings);
    }

    public static interface GetGitHubRepository {
        Observable<GitHubRepository> call(int repositoryId);
    }

    public static interface FetchAndGetGitHubRepository extends GetGitHubRepository {

    }

    public static interface GetGitHubRepositorySearch {
        Observable<GitHubRepositorySearch> call(String search);
    }
}

@@ -527,16 +527,41 @@
 esolver;
+%0Aimport android.util.Log;
 %0A%0Aimport
@@ -776,16 +776,87 @@
 Layer %7B%0A
+    private static final String TAG = DataLayer.class.getSimpleName();%0A
     priv
@@ -2584,24 +2584,132 @@
 chStore::put
+,%0A                        e -%3E Log.e(TAG, %22Error fetching GitHub repository search for '%22 + search + %22'%22, e)
 );%0A        r
@@ -3703,16 +3703,112 @@
 ore::put
+,%0A                        e -%3E Log.d(TAG, %22Error fetching GitHub repository %22 + repositoryId, e)
 );%0A    %7D

Add error handling to network requests