package org.zakariya.stickyheadersapp.api;

import android.text.TextUtils;
import android.util.Log;

import org.zakariya.stickyheadersapp.model.Person;
import org.zakariya.stickyheadersapp.model.RandomUserResults;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Singleton for accessing the http://api.randomuser.me API
 * Only performs the fetch once. Vends cached data subsequently.
 */
public class RandomUserLoader {

	private static final String TAG = RandomUserLoader.class.getSimpleName();

	private RandomUsersService service;
	private List<Person> randomUsers = new ArrayList<>();
	private ArrayList<OnLoadCallback> onLoadCallbacks = new ArrayList<>();
	private boolean loading;

	public interface OnLoadCallback {
		void onRandomUsersDidLoad(List<Person> randomUsers);
		void onFailure(Throwable t);
	}

	public RandomUserLoader() {
		Retrofit retrofit = new Retrofit.Builder()
				.baseUrl("http://api.randomuser.me")
				.addConverterFactory(GsonConverterFactory.create())
				.build();

		service = retrofit.create(RandomUsersService.class);
	}

	public void load(final OnLoadCallback onLoadCallback) {
		if (!randomUsers.isEmpty()) {
			onLoadCallback.onRandomUsersDidLoad(randomUsers);
			return;
		}

		onLoadCallbacks.add(onLoadCallback);
		if (loading) {
			return;
		}

		loading = true;
		int count = 50;
		String nationalities = "us,dk,fr,gb"; // stick with "western" names to keep sorting simple
		String seed = "qux";
		Call<RandomUserResults> call = service.randomUsers(count, nationalities, seed);
		call.enqueue(new Callback<RandomUserResults>() {
			@Override
			public void onResponse(Call<RandomUserResults> call, Response<RandomUserResults> response) {
				RandomUserResults results = response.body();

				if (!TextUtils.isEmpty(results.error)) {

					Log.e(TAG, "onResponse: got empty list, and error message: " + results.error);
					for (OnLoadCallback c : onLoadCallbacks) {
						c.onFailure(new Throwable(results.error));
					}

				} else if (results.results != null && results.results.length > 0) {

					randomUsers = sortUsers(Arrays.asList(results.results));
					for (OnLoadCallback c : onLoadCallbacks) {
						c.onRandomUsersDidLoad(randomUsers);
					}

				} else {

					Log.e(TAG, "onResponse: got empty list, and no error message from API");
					for (OnLoadCallback c : onLoadCallbacks) {
						c.onFailure(new Throwable("No data received"));
					}

				}
				loading = false;
			}

			@Override
			public void onFailure(Call<RandomUserResults> call, Throwable t) {
				Log.e(TAG, "onFailure: error: " + t.toString() );
				for (OnLoadCallback c : onLoadCallbacks) {
					c.onFailure(t);
				}
				loading = false;
			}
		});

	}

	private List<Person> sortUsers(List<Person> users) {
		Collections.sort(users, new Comparator<Person>() {
			@Override
			public int compare(Person lhs, Person rhs) {
				if (lhs.name.last.equalsIgnoreCase(rhs.name.last)) {
					return lhs.name.first.compareToIgnoreCase(rhs.name.first);
				}

				return lhs.name.last.compareToIgnoreCase(rhs.name.last);
			}
		});

		return users;
	}
}

@@ -1031,24 +1031,38 @@
 );%0A%09%09void on
+RandomUserLoad
 Failure(Thro
@@ -2174,32 +2174,46 @@
 ks) %7B%0A%09%09%09%09%09%09c.on
+RandomUserLoad
 Failure(new Thro
@@ -2619,32 +2619,46 @@
 ks) %7B%0A%09%09%09%09%09%09c.on
+RandomUserLoad
 Failure(new Thro
@@ -2695,24 +2695,53 @@
 %09%09%09%7D%0A%0A%09%09%09%09%7D%0A
+%09%09%09%09onLoadCallbacks.clear();%0A
 %09%09%09%09loading 
@@ -2856,16 +2856,30 @@
 TAG, %22on
+RandomUserLoad
 Failure:
@@ -2962,16 +2962,30 @@
 %09%09%09%09c.on
+RandomUserLoad
 Failure(
@@ -2990,24 +2990,53 @@
 e(t);%0A%09%09%09%09%7D%0A
+%09%09%09%09onLoadCallbacks.clear();%0A
 %09%09%09%09loading 

Fix memory leak in RandomUserLoader