package com.getbubblenow.android.repository;

import android.content.Context;
import android.util.Log;

import com.getbubblenow.android.api.ApiConstants;
import com.getbubblenow.android.api.network.ClientApi;
import com.getbubblenow.android.api.network.ClientService;
import com.getbubblenow.android.model.Sages;
import com.getbubblenow.android.util.UserStore;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import androidx.lifecycle.MutableLiveData;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.observers.DisposableSingleObserver;
import io.reactivex.schedulers.Schedulers;

/*package*/ class MessageRemoteLoader {

    private static final String TAG = "MessageRemoteLoader";

    private static final String PRE_AUTH_BUNDLE = "pre_auth";
    private static final String POST_AUTH_BUNDLE = "post_auth";
    private static final String API_SUFFIX = "/api/";

    private ClientApi clientApi;

    /*package*/ MessageRemoteLoader() {
        clientApi = ClientService.getInstance().createClientApi(ApiConstants.BOOTSTRAP_URL);
    }

    /*package*/ MutableLiveData<Map<String, String>> updatePreAuth(final Context context, final Locale locale) {
        final MutableLiveData<Map<String, String>> mutableLiveData = new MutableLiveData<>();
        clientApi.getSages()
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new DisposableSingleObserver<Sages>() {
                    @Override public void onSuccess(final Sages sages) {
                        // just get the first available
                        final String url = sages.getSages().get(0) + API_SUFFIX;
                        update(getLocaleBundle(locale), url, null, mutableLiveData);
                        dispose();
                    }

                    @Override public void onError(final Throwable e) {
                        Log.e(TAG, "Failed to connect to the remote server. " + e.getMessage(), e);
                        mutableLiveData.postValue(null);
                        dispose();
                    }
                });
        return mutableLiveData;
    }

    /*package*/ MutableLiveData<Map<String, String>> updatePostAuth(final Context context, final Locale locale) {
        final MutableLiveData<Map<String, String>> mutableLiveData = new MutableLiveData<>();
        final HashMap<String, String> header = new HashMap<>();
        header.put(ApiConstants.AUTHORIZATION_HEADER, UserStore.getInstance(context).getSageToken());
        final String url = UserStore.getInstance(context).getSageURL();
        update(getLocaleBundle(locale), url, header, mutableLiveData);
        return mutableLiveData;
    }

    private void update(
            final String localeBundle,
            final String url,
            final HashMap<String, String> header ,
            final  MutableLiveData<Map<String, String>> mutableLiveData) {
        clientApi = ClientService.getInstance().createClientApi(url);
        final Single<Map<String, String>> getMessageBundle = (header == null) ? clientApi.getMessageBundle(localeBundle, PRE_AUTH_BUNDLE)
                : clientApi.getMessageBundle(localeBundle, POST_AUTH_BUNDLE, header);
        getMessageBundle
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new DisposableSingleObserver<Map<String, String>>() {
                    @Override public void onSuccess(final Map<String, String> map) {
                        mutableLiveData.postValue(map);
                        dispose();
                    }

                    @Override public void onError(final Throwable e) {
                        Log.e(TAG, "Failed to get localization data from the remote server. " + e.getMessage(), e);
                        mutableLiveData.postValue(null);
                        dispose();
                    }
                });
    }

    private String getLocaleBundle(final Locale locale) {
        return locale.getLanguage() + '_' + locale.getCountry();
    }
}
