/*
 * 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.cryptolib.elgamal.bean;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.commons.utils.validations.Validate;

/**
 * Representation of an ElGamal key pair. This key pair is composed of a private
 * key and a public key.
 * <P>
 * Internally, the private key consists of a list of exponents and the public
 * key consists of a list of Zp group elements.
 */
public final class ElGamalKeyPair {

    private final ElGamalPrivateKey _privateKey;

    private final ElGamalPublicKey _publicKey;

    /**
     * Creates an ElGamalKeyPair from the specified private and public keys.
     * <P>
     * These keys should be compatible with each other, and if they are to be
     * used together, then they should have the correct mathematical
     * relationships with each other. They should meet the following conditions:
     * <ul>
     * <li>They contain the same number of elements.</li>
     * <li>They belong to the same mathematical group.</li>
     * <li>They have the correct mathematical relationship. This condition is
     * not checked in this constructor, however if it is not met, then it will
     * not be possible to successfully encrypt and decrypt data using these
     * keys.</li>
     * </ul>
     * 
     * @param privateKey
     *            the private key to be set in the key pair.
     * @param publicKey
     *            the public key to be set in the key pair.
     * @throws GeneralCryptoLibException
     *             if private or public key is invalid.
     */
    public ElGamalKeyPair(final ElGamalPrivateKey privateKey,
            final ElGamalPublicKey publicKey)
            throws GeneralCryptoLibException {

        Validate.notNull(privateKey, "ElGamal private key");
        Validate.notNull(publicKey, "ElGamal public key");
        Validate.equals(privateKey.getKeys().size(), publicKey.getKeys()
            .size(), "ElGamal private key length",
            "ElGamal public key length");
        if (!privateKey.getGroup().equals(publicKey.getGroup())) {
            throw new GeneralCryptoLibException(
                "ElGamal public and private keys must belong to same mathematical group.");
        }
        _privateKey = privateKey;
        _publicKey = publicKey;
    }

    /**
     * Retrieves the {@link ElGamalPrivateKey}.
     * 
     * @return the {@link ElGamalPrivateKey}.
     */
    public ElGamalPrivateKey getPrivateKeys() {

        return _privateKey;
    }

    /**
     * Retrieves the {@link ElGamalPublicKey}.
     * 
     * @return the {@link ElGamalPublicKey}.
     */
    public ElGamalPublicKey getPublicKeys() {

        return _publicKey;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
            + ((_privateKey == null) ? 0 : _privateKey.hashCode());
        result = prime * result
            + ((_publicKey == null) ? 0 : _publicKey.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        ElGamalKeyPair other = (ElGamalKeyPair) obj;
        if (_privateKey == null) {
            if (other._privateKey != null) {
                return false;
            }
        } else if (!_privateKey.equals(other._privateKey)) {
            return false;
        }
        if (_publicKey == null) {
            if (other._publicKey != null) {
                return false;
            }
        } else if (!_publicKey.equals(other._publicKey)) {
            return false;
        }
        return true;
    }
}
