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

import android.graphics.drawable.Drawable;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Presence;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.android.MercuryImApplication;
import org.mercury_im.messenger.android.ui.avatar.AvatarDrawable;
import org.mercury_im.messenger.android.ui.base.MercuryAndroidViewModel;
import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.core.viewmodel.contact.ContactDetailViewModel;
import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem;
import org.pgpainless.key.OpenPgpV4Fingerprint;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

import javax.inject.Inject;

import io.reactivex.Completable;
import io.reactivex.Single;
import lombok.SneakyThrows;

public class AndroidContactDetailViewModel extends ViewModel implements MercuryAndroidViewModel<ContactDetailViewModel> {

    @Inject
    ContactDetailViewModel commonViewModel;

    private MutableLiveData<UUID> contactAccountId = new MutableLiveData<>(UUID.randomUUID());
    private MutableLiveData<String> contactAddress = new MutableLiveData<>("alice@wonderland.lit");
    private MutableLiveData<Drawable> contactAvatar = new MutableLiveData<>(new AvatarDrawable("Alice Wonderland", "alice@wonderland.lit"));
    private MutableLiveData<Presence.Mode> contactPresenceMode = new MutableLiveData<>(Presence.Mode.available);
    private MutableLiveData<String> contactPresenceStatus = new MutableLiveData<>("Going down the rabbit hole.");
    private MutableLiveData<String> contactName = new MutableLiveData<>("Alice Wonderland");
    private MutableLiveData<String> contactAccountAddress = new MutableLiveData<>("mad@hatter.lit");
    private MutableLiveData<List<String>> contactGroups = new MutableLiveData<>(Collections.emptyList());
    private MutableLiveData<List<FingerprintViewItem>> contactFingerprints = new MutableLiveData<>(Collections.emptyList());
    private MutableLiveData<Optional<FingerprintViewItem>> contactIkeyFingerprint = new MutableLiveData<>(new Optional<>());

    public AndroidContactDetailViewModel() {
        super();
        MercuryImApplication.getApplication().getAppComponent().inject(this);
    }

    public Completable init(UUID peerId) {
        return getCommonViewModel().init(peerId)

                .andThen(Completable.fromAction(() -> {
                    addDisposable(commonViewModel.getContactAccountAddress()
                            .map(Objects::toString)
                            .subscribe(contactAccountAddress::postValue));
                    addDisposable(commonViewModel.getContactAddress()
                            .map(Objects::toString)
                            .subscribe(contactAddress::postValue));
                    addDisposable(commonViewModel.getContactDisplayName().subscribe(contactName::postValue));
                    addDisposable(commonViewModel.getContactPresenceMode().subscribe(contactPresenceMode::postValue));
                    addDisposable(commonViewModel.getContactPresenceStatus().subscribe(contactPresenceStatus::postValue));
                    addDisposable(commonViewModel.getContactGroups().subscribe(contactGroups::postValue));
                    addDisposable(commonViewModel.getContactAvatarBase()
                            .map(tuple -> new AvatarDrawable(tuple.getFirst(), tuple.getSecond().toString()))
                            .subscribe(contactAvatar::postValue));
                    addDisposable(commonViewModel.getContactIdentityFingerprint().subscribe(contactIkeyFingerprint::postValue));
                    addDisposable(commonViewModel.getContactDeviceFingerprints().subscribe(contactFingerprints::postValue));
                }));
    }

    public LiveData<String> getContactAddress() {
        return contactAddress;
    }

    public LiveData<UUID> getAccountId() {
        return contactAccountId;
    }

    public LiveData<Drawable> getContactAvatar() {
        return contactAvatar;
    }

    public LiveData<Presence.Mode> getContactPresenceMode() {
        return contactPresenceMode;
    }

    public LiveData<String> getContactName() {
        return contactName;
    }

    public LiveData<String> getContactPresenceStatus() {
        return contactPresenceStatus;
    }

    public LiveData<String> getContactAccountAddress() {
        return contactAccountAddress;
    }

    public LiveData<List<String>> getContactGroups() {
        return contactGroups;
    }

    public LiveData<Optional<FingerprintViewItem>> getContactIdentityFingerprint() {
        return contactIkeyFingerprint;
    }

    public LiveData<List<FingerprintViewItem>> getContactDeviceFingerprints() {
        return contactFingerprints;
    }

    public Single<UUID> getOrCreateChat() {
        return commonViewModel.getOrCreateChat();
    }

    public void changeContactName(String newName)
            throws XMPPException.XMPPErrorException, SmackException.NotConnectedException,
            InterruptedException, SmackException.NoResponseException {
        commonViewModel.changeContactName(newName);
    }


    @SneakyThrows
    public void markDeviceFingerprintTrusted(OpenPgpV4Fingerprint fingerprint, boolean checked) {
        commonViewModel.markDeviceFingerprintTrusted(fingerprint, checked);
    }

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

    public void markIkeyFingerprintTrusted(OpenPgpV4Fingerprint fingerprint, EntityBareJid owner, boolean isChecked) {
        commonViewModel.markIkeyFingerprintTrusted(fingerprint, owner, isChecked);
    }
}
