package co.pixelbeard.theanfieldwrap.data.source.local;

import android.content.Context;

import com.google.firebase.crashlytics.FirebaseCrashlytics;
import com.tonyodev.fetch2.Fetch;

import java.util.List;

import co.pixelbeard.theanfieldwrap.data.NotificationSetting;
import co.pixelbeard.theanfieldwrap.data.Podcast;
import co.pixelbeard.theanfieldwrap.data.PodcastStateModel;
import co.pixelbeard.theanfieldwrap.data.RealmPodcast;
import co.pixelbeard.theanfieldwrap.data.User;
import co.pixelbeard.theanfieldwrap.data.responses.ArticleByIdResponse;
import co.pixelbeard.theanfieldwrap.data.responses.ArticlesResponse;
import co.pixelbeard.theanfieldwrap.data.responses.GenericResponse;
import co.pixelbeard.theanfieldwrap.data.responses.GetDevicesResponse;
import co.pixelbeard.theanfieldwrap.data.responses.GetWalletResponse;
import co.pixelbeard.theanfieldwrap.data.responses.GuestUserResponse;
import co.pixelbeard.theanfieldwrap.data.responses.LoginResponse;
import co.pixelbeard.theanfieldwrap.data.responses.NotificationSettingsResponse;
import co.pixelbeard.theanfieldwrap.data.responses.PodcastByIdResponse;
import co.pixelbeard.theanfieldwrap.data.responses.PodcastsResponse;
import co.pixelbeard.theanfieldwrap.data.responses.RegisterUserResponse;
import co.pixelbeard.theanfieldwrap.data.responses.SubscriptionItemResponse;
import co.pixelbeard.theanfieldwrap.data.responses.VideoByIdResponse;
import co.pixelbeard.theanfieldwrap.data.responses.VideosResponse;
import co.pixelbeard.theanfieldwrap.data.source.DataSource;
import co.pixelbeard.theanfieldwrap.downloader.DownloadConstants;
import co.pixelbeard.theanfieldwrap.freeSubscription.ActiveSubscriptionResponse;
import co.pixelbeard.theanfieldwrap.utils.PrefKey;
import co.pixelbeard.theanfieldwrap.utils.PrefUtils;
import io.reactivex.Observable;
import io.realm.Realm;
import io.realm.RealmAsyncTask;
import io.realm.RealmResults;

public class LocalRepository implements DataSource {
    private Realm realm;

    public LocalRepository(Realm realm) {
        this.realm = realm;
    }

    @Override
    public Observable<GenericResponse> recordAnalytic(String type, String variable, String secondaryVariable) {
        //Remote only
        return null;
    }

    @Override
    public Observable<LoginResponse> login(String email, String password) {
        //Remote Only
        return null;
    }

    @Override
    public void saveUserDetails(User user, String authToken) {

        PrefUtils.getInstance().putStringPref(PrefKey.USERNAME, user.getUsername());
        PrefUtils.getInstance().putStringPref(PrefKey.AUTH_TOKEN, authToken);
        PrefUtils.getInstance().putBooleanPref(PrefKey.LOGGED_IN, true);
        PrefUtils.getInstance().putBooleanPref(PrefKey.IS_GUEST_ACCOUNT, false);

        PrefUtils.getInstance().putStringPref(PrefKey.FIRSTNAME, user.getFirstName());
        PrefUtils.getInstance().putStringPref(PrefKey.LASTNAME, user.getLastName());
        PrefUtils.getInstance().putStringPref(PrefKey.EMAIL, user.getEmail());
        PrefUtils.getInstance().putStringPref(PrefKey.AVATAR, user.getAvatar());
        PrefUtils.getInstance().putIntPref(PrefKey.AUTH_LEVEL, user.getAuthLevel());
        PrefUtils.getInstance().putLongPref(PrefKey.USER_ID, user.getUserId());
        PrefUtils.getInstance().putIntPref(PrefKey.BANNED, user.getBanned());
        PrefUtils.getInstance().putStringPref(PrefKey.AMEMBER_USER_ID, user.getaMemberUserId());
        PrefUtils.getInstance().putStringPref(PrefKey.AMEMBER_EMAIL, user.getaMemberEmail());
        PrefUtils.getInstance().putBooleanPref(PrefKey.SHOW_SUBSCRIPTION_FREE, user.getShowFreeSubscription());
        PrefUtils.getInstance().storeSubs(user.getSubscriptions());
    }

    @Override
    public void saveUserDetails(String firstName, String lastName, String userName) {
        PrefUtils.getInstance().putStringPref(PrefKey.FIRSTNAME, firstName);
        PrefUtils.getInstance().putStringPref(PrefKey.LASTNAME, lastName);
        PrefUtils.getInstance().putStringPref(PrefKey.USERNAME, userName);
    }

    @Override
    public Observable<GuestUserResponse> registerGuestUser() {
        //Remote Only
        return null;
    }

    @Override
    public void saveGuestUserDetails(String userName, String authToken) {
        PrefUtils.getInstance().putStringPref(PrefKey.USERNAME, userName);
        PrefUtils.getInstance().putStringPref(PrefKey.AUTH_TOKEN, authToken);
        PrefUtils.getInstance().putBooleanPref(PrefKey.LOGGED_IN, true);
        PrefUtils.getInstance().putBooleanPref(PrefKey.IS_GUEST_ACCOUNT, true);
    }

    @Override
    public Observable<RegisterUserResponse> registerFullUser(String firstName, String lastName, String email, String password, boolean optIn, String username, String country) {
        //Remote only
        return null;
    }

    @Override
    public Observable<GenericResponse> checkEmailAvailable(String email) {
        //Remote only
        return null;
    }

    @Override
    public Observable<GenericResponse> checkUsernameAvailable(String username) {
        //Remote only
        return null;
    }

    @Override
    public Observable<GenericResponse> resendAuthCode(String email) {
        //Remote only
        return null;
    }

    @Override
    public Observable<GenericResponse> activateUser(String email, String activationCode) {
        //Remote only
        return null;
    }

    @Override
    public Observable<GenericResponse> changePassword(String oldPassword, String newPassword) {
        //Remote only
        return null;
    }

    @Override
    public Observable<NotificationSettingsResponse> getUserSettings() {
        //Remote only
        return null;
    }

    @Override
    public List<NotificationSetting> getUserSettingsLocal() {
        return PrefUtils.getInstance().getSettings();
    }

    @Override
    public void saveUserSettings(List<NotificationSetting> settings) {
        PrefUtils.getInstance().storeSettings(settings);
    }

    @Override
    public Observable<GenericResponse> updateUserSetting(String type, int value) {
        //Remote only
        return null;
    }

    @Override
    public Observable<GenericResponse> updateUserEmail(String oldEmail, String newEmail) {
        //Remote only
        return null;
    }

    @Override
    public Observable<GenericResponse> updateUserDetails(String firstName, String lastName, String userName) {

        return null;
    }

    @Override
    public Observable<GenericResponse> requestPasswordReset(String email) {
        //Remote only
        return null;
    }

    @Override
    public Observable<GenericResponse> resetPassword(String email, String recoveryCode, String password) {
        //Remote Only
        return null;
    }

    @Override
    public Observable<GenericResponse> logout() {
        //We don't need to return the observable here, however we can use this method to clear our SharedPreferences of all user data

        PrefUtils.getInstance().clearPrefs();
        FirebaseCrashlytics.getInstance().setUserId(""); // Reset the User ID to blank
        return null;
    }

    @Override
    public void clearAllData(Context context) {
        DownloadConstants.deleteDownloadsDirectory(context);
        Fetch.Impl.getDefaultInstance().removeAll();
        realm.executeTransactionAsync(realm1 -> realm1.where(RealmPodcast.class).findAll().deleteAllFromRealm());

    }

    @Override
    public Observable<PodcastsResponse> getPodcasts(int pageNum) {
        //Remote only
        return null;
    }

    @Override
    public Observable<PodcastByIdResponse> getPodcastByIdRemote(Long podcastId) {
        //Remote only, may be used in future if we go full offline
        return null;
    }

    @Override
    public Observable<ArticlesResponse> getArticles(int pageNum) {
        //remote only
        return null;
    }

    @Override
    public Observable<ArticleByIdResponse> getArticleById(Long articleId) {
        //Remote only
        return null;
    }

    @Override
    public Observable<VideosResponse> getVideos(int pageNum) {
        //Remote only
        return null;
    }

    @Override
    public Observable<VideoByIdResponse> getVideoById(String videoId) {
        //Remote only
        return null;
    }

    @Override
    public Observable<LoginResponse> checkUserSubscription() {
        //Remote only
        return null;
    }

    @Override
    public Observable<GenericResponse> convertGuestToFullUser(String firstName, String lastName, String email, String password, boolean optIn, String username, String country) {
        //Remote only
        return null;
    }

    @Override
    public void getDownloadedPodcasts(DownloadedPodcastCallback callback) {


        RealmResults<RealmPodcast> results = realm.where(RealmPodcast.class).findAllAsync();

        results.addChangeListener(podcasts -> {
            results.removeAllChangeListeners();
            callback.onPodcastsRetrieved(results);
        });

    }

    @Override
    public void downloadPodcast(Podcast podcast, Context context) {
        //Remote only
    }


    @Override
    public void savePodcast(Podcast podcast, String filePath) {

        final RealmPodcast obj = new RealmPodcast(podcast, filePath);

        RealmAsyncTask task = realm.executeTransactionAsync(realm -> realm.copyToRealmOrUpdate(obj),
                Throwable::printStackTrace);

    }

    @Override
    public RealmPodcast getPodcastByIdLocal(long id) {
        return realm.where(RealmPodcast.class).equalTo("postId", id).findFirst();
    }

    @Override
    public Observable<GetDevicesResponse> getActiveDevices() {
        //Remote only
        return null;
    }

    @Override
    public Observable<GenericResponse> unlinkDevice(String userApiToken, int deviceId) {
        //Remote only
        return null;
    }

    @Override
    public Observable<GetWalletResponse> getWallet() {
        //Remote only
        return null;
    }

    @Override
    public Observable<GetWalletResponse> creditUserAccount(int value, String title, String purchaseToken) {
        //Remote only
        return null;
    }

    @Override
    public Observable<GetWalletResponse> purchaseItem(String productId) {
        //Remote only
        return null;
    }

    @Override
    public void getPodcastStates(PodcastStateCallback callback) {
        PodcastStateModel podcastState = realm.where(PodcastStateModel.class).findFirstAsync();
        podcastState.addChangeListener(state -> {
            podcastState.removeAllChangeListeners();
            if (podcastState.isValid()) {

                callback.onPodcastState(realm.copyFromRealm(podcastState), -1);
            }
        });
    }

    @Override
    public void clearPodcastStates() {
        realm.executeTransactionAsync(realm1 -> realm1.where(PodcastStateModel.class).findAll().deleteAllFromRealm());
    }

    @Override
    public void getPodcastState(long podcastId, int position, PodcastStateCallback callback) {

        PodcastStateModel podcastState = realm.where(PodcastStateModel.class).equalTo("postId", podcastId).findFirstAsync();

        podcastState.addChangeListener(state -> {
            podcastState.removeAllChangeListeners();

            callback.onPodcastState(podcastState, position);
        });
    }

    @Override
    public Observable<SubscriptionItemResponse> getSubscription() {
        return null;
    }

    @Override
    public Observable<ActiveSubscriptionResponse> activeSubscription(String subscription) {
        return null;
    }

    @Override
    public Observable<ActiveSubscriptionResponse> activePaidSubscription(String subscription, String planType, int duration, String purchaseToken) {
        return null;
    }

    public void onDestroyRepo() {
        //Kill Realm instance
//        try {
//            if (realm.isInTransaction()) {
//                realm.cancelTransaction();
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }

//        realm = null;
    }
}
