package org.mercury_im.messenger.core.crypto.ikey;

import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.jivesoftware.smackx.ikey.record.IkeyRecord;
import org.jivesoftware.smackx.ikey.record.IkeyStore;
import org.jivesoftware.smackx.ox.OpenPgpSecretKeyBackupPassphrase;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.util.Optional;

import java.io.IOException;
import java.util.UUID;

/**
 * Adapter that serves as a {@link IkeyStore} implementation wrapping a {@link IkeyRepository}.
 */
public class IkeyStoreAdapter implements IkeyStore {

    private final UUID accountId;
    private final IkeyRepository repository;
    private final SchedulersFacade schedulers;

    public IkeyStoreAdapter(UUID accountId, IkeyRepository repository, SchedulersFacade schedulers) {
        this.accountId = accountId;
        this.repository = repository;
        this.schedulers = schedulers;
    }

    @Override
    public IkeyRecord loadIkeyRecord(EntityBareJid jid) throws IOException {
        return repository.loadRecord(accountId, jid)
                .compose(schedulers.executeUiSafeObservable())
                .firstElement()
                .blockingGet();
    }

    @Override
    public void storeIkeyRecord(EntityBareJid jid, IkeyRecord record) throws IOException {
        repository.storeRecord(accountId, jid, record)
                .compose(schedulers.executeUiSafeCompletable())
                .subscribe();
    }

    @Override
    public IkeyRecord loadContenderIkeyRecord(EntityBareJid jid) throws IOException {
        return repository.loadContenderRecord(accountId, jid)
                .compose(schedulers.executeUiSafeObservable())
                .firstElement()
                .blockingGet();
    }

    @Override
    public void storeContenderIkeyRecord(EntityBareJid jid, IkeyRecord element) throws IOException {
        repository.storeContenderRecord(accountId, jid, element)
                .compose(schedulers.executeUiSafeCompletable())
                .subscribe();
    }

    @Override
    public void clearContenderIkeyRecord(EntityBareJid jid) throws IOException {
        repository.clearContenderRecord(accountId, jid)
                .compose(schedulers.executeUiSafeCompletable())
                .subscribe();
    }

    @Override
    public PGPSecretKeyRing loadSecretKey() {
        return repository.loadSecretKey(accountId)
                .compose(schedulers.executeUiSafeObservable())
                .firstElement()
                .blockingGet()
                .getItem();
    }

    @Override
    public void storeSecretKey(PGPSecretKeyRing secretKey) {
        repository.storeSecretKey(accountId, secretKey).blockingAwait();
    }

    @Override
    public OpenPgpSecretKeyBackupPassphrase loadBackupPassphrase() {
        Optional<OpenPgpSecretKeyBackupPassphrase> passphrase = repository.loadBackupPassphrase(accountId)
                .compose(schedulers.executeUiSafeSingle())
                .blockingGet();
        return passphrase.isPresent() ? passphrase.getItem() : null;
    }

    @Override
    public void storeBackupPassphrase(OpenPgpSecretKeyBackupPassphrase passphrase) {
        repository.storeBackupPassphrase(accountId, passphrase)
                .blockingAwait();
    }
}
