package org.mercury_im.messenger.android.ui.account.detail;

import android.app.Application;

import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;

import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import org.mercury_im.messenger.android.MercuryImApplication;
import org.mercury_im.messenger.android.ui.MercuryAndroidViewModel;
import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.core.viewmodel.account.detail.AccountDetailsViewModel;
import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem;
import org.pgpainless.key.OpenPgpV4Fingerprint;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.inject.Inject;

import io.reactivex.Completable;

public class AndroidAccountDetailsViewModel extends AndroidViewModel implements MercuryAndroidViewModel<AccountDetailsViewModel> {

    private static final Logger LOGGER = Logger.getLogger(AndroidAccountDetailsViewModel.class.getName());

    @Inject
    SchedulersFacade schedulers;

    @Inject
    AccountDetailsViewModel commonViewModel;

    private final UUID accountId;
    private MutableLiveData<OpenPgpV4Fingerprint> localFingerprint = new MutableLiveData<>(new OpenPgpV4Fingerprint("09858F60046289311743B90F3152226EB43287C5"));
    private MutableLiveData<List<FingerprintViewItem>> remoteFingerprints = new MutableLiveData<>(new ArrayList<>());
    private MutableLiveData<EntityBareJid> jid = new MutableLiveData<>(JidCreate.entityBareFromOrThrowUnchecked("placeholder@place.holder"));

    public AndroidAccountDetailsViewModel(@NonNull Application application, UUID accountId) {
        super(application);
        this.accountId = accountId;

        LOGGER.log(Level.INFO, "Creating AndroidAccountDetailsViewModel");
        ((MercuryImApplication) application).getAppComponent().inject(this);

        addDisposable(getCommonViewModel().observeLocalFingerprint(accountId)
                .compose(schedulers.executeUiSafeObservable())
                .filter(Optional::isPresent)
                .map(Optional::getItem)
                .subscribe(localFingerprint::postValue));

        addDisposable(getCommonViewModel().observeRemoteFingerprints(accountId)
                .compose(schedulers.executeUiSafeObservable())
                .subscribe(list -> {
                            LOGGER.log(Level.INFO, "Set remote fingerprints to list: " + Arrays.toString(list.toArray()));
                            remoteFingerprints.postValue(list);
                        },
                        e -> LOGGER.log(Level.SEVERE, "Error observing remote fingerprints.", e),
                        () -> LOGGER.log(Level.INFO, "observing remote fingerprint onComplete.")));

        addDisposable(getCommonViewModel().getJid(accountId).subscribe(jid::postValue));
    }

    @Override
    public AccountDetailsViewModel getCommonViewModel() {
        return commonViewModel;
    }

    public LiveData<EntityBareJid> getJid() {
        return jid;
    }

    public void markFingerprintTrusted(OpenPgpV4Fingerprint fingerprint, boolean trusted) {
        getCommonViewModel().markFingerprintTrusted(accountId, fingerprint, trusted);
    }

    public LiveData<OpenPgpV4Fingerprint> getLocalFingerprint() {
        return localFingerprint;
    }

    public LiveData<List<FingerprintViewItem>> getRemoteFingerprints() {
        return remoteFingerprints;
    }

    public void unpublishPublicKey(OpenPgpV4Fingerprint fingerprint) {
        addDisposable(getCommonViewModel().unpublishPublicKey(accountId, fingerprint)
                .subscribeOn(schedulers.getNewThread())
                .observeOn(schedulers.getUiScheduler())
                .subscribe(() -> LOGGER.log(Level.INFO, "Successfully unpublished fingerprint " + fingerprint),
                        e -> LOGGER.log(Level.SEVERE, "Error unpublishing fingerprint " + fingerprint, e)));
    }

    public static class AndroidAccountDetailsViewModelFactory implements ViewModelProvider.Factory {

        private final Application application;
        private final UUID accountId;

        public AndroidAccountDetailsViewModelFactory(Application application, UUID accountId) {
            this.application = application;
            this.accountId = accountId;
        }

        @NonNull
        @Override
        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
            return (T) new AndroidAccountDetailsViewModel(application, accountId);
        }
    }
}
