/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.products.ov.channel.cc.commons.keymanagement;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.elgamal.bean.ElGamalEncryptionParameters;
import com.scytl.cryptolib.elgamal.bean.ElGamalPrivateKey;
import com.scytl.cryptolib.elgamal.bean.ElGamalPublicKey;
import com.scytl.cryptolib.elgamal.cryptoapi.EncryptionParameters;
import com.scytl.cryptolib.mathematical.groups.impl.ZpSubgroup;

/**
 * Choice code keys container.
 */
class ChoiceCodeKeys {
    private final ElGamalPrivateKey generationPrivateKey;

    private final ElGamalPublicKey generationPublicKey;

    private final byte[] generationPublicKeySignature;

    private final ElGamalPrivateKey decryptionPrivateKey;

    private final ElGamalPublicKey decryptionPublicKey;

    private final byte[] decryptionPublicKeySignature;

    private final EncryptionParameters encryptionParameters;

    private ChoiceCodeKeys(ElGamalPrivateKey generationPrivateKey, ElGamalPublicKey generationPublicKey,
            byte[] generationPublicKeySignature, ElGamalPrivateKey decryptionPrivateKey,
            ElGamalPublicKey decryptionPublicKey, byte[] decryptionPublicKeySignature,
            EncryptionParameters encryptionParameters) {
        this.generationPrivateKey = generationPrivateKey;
        this.generationPublicKey = generationPublicKey;
        this.generationPublicKeySignature = generationPublicKeySignature;
        this.decryptionPrivateKey = decryptionPrivateKey;
        this.decryptionPublicKey = decryptionPublicKey;
        this.decryptionPublicKeySignature = decryptionPublicKeySignature;
        this.encryptionParameters = encryptionParameters;
    }

    /**
     * Returns the decryption private key.
     * 
     * @return the decryption private key.
     */
    public ElGamalPrivateKey decryptionPrivateKey() {
        return decryptionPrivateKey;
    }

    /**
     * Returns the decryption public key.
     * 
     * @return the decryption public key.
     */
    public ElGamalPublicKey decryptionPublicKey() {
        return decryptionPublicKey;
    }

    /**
     * Returns the decryption public key signature.
     * 
     * @return the decryption public key signature.
     */
    public byte[] decryptionPublicKeySignature() {
        return decryptionPublicKeySignature;
    }

    /**
     * Returns the encryptionParameters.
     * 
     * @return the encryptionParameters.
     */
    public EncryptionParameters encryptionParameters() {
        return encryptionParameters;
    }

    /**
     * Returns the generation private key.
     * 
     * @return the generation private key.
     */
    public ElGamalPrivateKey generationPrivateKey() {
        return generationPrivateKey;
    }

    /**
     * Returns the generation public key.
     * 
     * @return the generation public key.
     */
    public ElGamalPublicKey generationPublicKey() {
        return generationPublicKey;
    }

    /**
     * Returns the generation public key signature.
     * 
     * @return the generation public key signature.
     */
    public byte[] generationPublicKeySignature() {
        return generationPublicKeySignature;
    }

    /**
     * Builder for creating {@link ChoiceCodeKeys} instances.
     */
    static class Builder {
        private ElGamalPrivateKey generationPrivateKey;

        private ElGamalPublicKey generationPublicKey;

        private byte[] generationPublicKeySignature;

        private ElGamalPrivateKey decryptionPrivateKey;

        private ElGamalPublicKey decryptionPublicKey;

        private byte[] decryptionPublicKeySignature;

        /**
         * Builds a new {@link ChoiceCodeKeys} instance.
         * 
         * @return a new instance.
         */
        public ChoiceCodeKeys build() {
            ZpSubgroup group = generationPrivateKey.getGroup();
            EncryptionParameters encryptionParameters;
            try {
                encryptionParameters = new ElGamalEncryptionParameters(group.getP(), group.getQ(), group.getG());
            } catch (GeneralCryptoLibException e) {
                throw new IllegalStateException("Failed to get encryption parameters from the generation private key.",
                    e);
            }
            return new ChoiceCodeKeys(generationPrivateKey, generationPublicKey, generationPublicKeySignature,
                decryptionPrivateKey, decryptionPublicKey, decryptionPublicKeySignature, encryptionParameters);
        }

        /**
         * Sets the decryption keys.
         * 
         * @param privateKey
         *            the private key
         * @param publicKey
         *            th public key
         * @param publicKeySignature
         *            the publiv ckey signature
         * @return this instance.
         */
        public Builder setDecryptionKeys(ElGamalPrivateKey privateKey, ElGamalPublicKey publicKey,
                byte[] publicKeySignature) {
            decryptionPrivateKey = privateKey;
            decryptionPublicKey = publicKey;
            decryptionPublicKeySignature = publicKeySignature;
            return this;
        }

        /**
         * Sets the generation keys.
         * 
         * @param privateKey
         *            the private key
         * @param publicKey
         *            th public key
         * @param publicKeySignature
         *            the publiv ckey signature
         * @return this instance.
         */
        public Builder setGenerationKeys(ElGamalPrivateKey privateKey, ElGamalPublicKey publicKey,
                byte[] publicKeySignature) {
            generationPrivateKey = privateKey;
            generationPublicKey = publicKey;
            generationPublicKeySignature = publicKeySignature;
            return this;
        }
    }
}
