package ch.threema.domain.helpers;

import androidx.annotation.NonNull;
import ch.threema.domain.stores.IdentityStore;

import ch.threema.base.crypto.NaCl;
import ch.threema.libthreema.CryptoException;

/**
 * An in-memory identity store, used for testing.
 */
public class InMemoryIdentityStore implements IdentityStore {
    private String identity;
    private String serverGroup;
    private byte[] publicKey;
    private byte[] privateKey;
    private final String publicNickname;

    public InMemoryIdentityStore(String identity, String serverGroup, byte[] privateKey, String publicNickname) {
        this.identity = identity;
        this.serverGroup = serverGroup;
        try {
            this.publicKey = NaCl.derivePublicKey(privateKey);
        } catch (CryptoException e) {
            throw new RuntimeException(e);
        }
        this.privateKey = privateKey;
        this.publicNickname = publicNickname;
    }

    @Override
    public byte[] encryptData(@NonNull byte[] plaintext, @NonNull byte[] nonce, @NonNull byte[] receiverPublicKey) {
        try {
            NaCl nacl = new NaCl(privateKey, receiverPublicKey);
            return nacl.encrypt(plaintext, nonce);
        } catch (CryptoException e) {
            return null;
        }
    }

    @Override
    public byte[] decryptData(@NonNull byte[] ciphertext, @NonNull byte[] nonce, @NonNull byte[] senderPublicKey) {
        try {
            NaCl nacl = new NaCl(privateKey, senderPublicKey);
            return nacl.decrypt(ciphertext, nonce);
        } catch (CryptoException e) {
            return null;
        }
    }

    @Override
    public byte[] calcSharedSecret(@NonNull byte[] publicKey) {
        try {
            NaCl nacl = new NaCl(privateKey, publicKey);
            return nacl.sharedSecret;
        } catch (CryptoException e) {
            return null;
        }
    }

    @Override
    public String getIdentityString() {
        return identity;
    }

    @Override
    public String getServerGroup() {
        return serverGroup;
    }

    @Override
    public byte[] getPublicKey() {
        return publicKey;
    }

    @Override
    public byte[] getPrivateKey() {
        return privateKey;
    }

    @Override
    @NonNull
    public String getPublicNickname() {
        if (publicNickname == null) {
            return "";
        }
        return publicNickname;
    }

    @Override
    public void setPublicNickname(@NonNull String publicNickname) {
        throw new RuntimeException("not implemented");
    }

    @Override
    public void storeIdentity(
        @NonNull String identity,
        @NonNull String serverGroup,
        @NonNull byte[] privateKey
    ) {
        this.identity = identity;
        this.serverGroup = serverGroup;
        try {
            this.publicKey = NaCl.derivePublicKey(privateKey);
        } catch (CryptoException e) {
            throw new RuntimeException(e);
        }
        this.privateKey = privateKey;
    }

    @Override
    public void clear() {
        throw new RuntimeException("not implemented");
    }
}
