/*
 * 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.proofs.maurer.factory;

import java.util.ArrayList;
import java.util.List;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.mathematical.groups.GroupElement;
import com.scytl.cryptolib.mathematical.groups.MathematicalGroup;
import com.scytl.cryptolib.primitives.messagedigest.configuration.ConfigMessageDigestAlgorithmAndProvider;
import com.scytl.cryptolib.proofs.maurer.configuration.ConfigProofHashCharset;
import com.scytl.cryptolib.proofs.maurer.function.PhiFunctionSchnorr;
import com.scytl.cryptolib.proofs.proof.Proof;

/**
 * Schnorr proof verifier.
 * 
 * @param <T>
 *            the type which parameterizes the group elements of the
 *            {@link MathematicalGroup} that will be used during this exchange.
 * @param <E>
 *            the type of the group elements of the {@link MathematicalGroup}
 *            that will be used during this exchange. E must be a type which
 *            extends GroupElement{@code <T>}.
 */
public final class SchnorrProofVerifier<T, E extends GroupElement<T>> {

    private final E _exponentiatedElement;

    private final String _voterID;

    private final String _electionEventID;

    private final Proof _proof;

    private final MathematicalGroup<E> _group;

    private final ConfigMessageDigestAlgorithmAndProvider _configMessageDigestAlgorithmAndProvider;

    private final ConfigProofHashCharset _configProofHashCharset;

    /**
     * Default constructor.
     * 
     * @param exponentiatedElement
     *            the exponentiated generator element.
     * @param voterID
     *            the voter identification number, which forms part of the proof
     *            generation business data.
     * @param electionEventID
     *            the election event identification number, which forms part of
     *            the proof generation business data.
     * @param proof
     *            the proof to be verified.
     * @param group
     *            the Zp subgroup used for exponentiation.
     * @param configMessageDigestAlgorithmAndProvider
     *            the algorithm and provider of the message digest used to
     *            generate the proof.
     * @param configProofHashCharset
     *            the character set of the hash used to generate the proof.
     * @throws GeneralCryptoLibException
     *             if the phi function cannot be created.
     */
    SchnorrProofVerifier(
            final E exponentiatedElement,
            final String voterID,
            final String electionEventID,
            final Proof proof,
            final MathematicalGroup<E> group,
            final ConfigMessageDigestAlgorithmAndProvider configMessageDigestAlgorithmAndProvider,
            final ConfigProofHashCharset configProofHashCharset)
            throws GeneralCryptoLibException {

        _exponentiatedElement = exponentiatedElement;
        _voterID = voterID;
        _electionEventID = electionEventID;
        _proof = proof;
        _group = group;

        _configMessageDigestAlgorithmAndProvider =
            configMessageDigestAlgorithmAndProvider;
        _configProofHashCharset = configProofHashCharset;
    }

    /**
     * Verifies a schnorr proof.
     *
     * @return true if the proof is verified as true, false otherwise.
     * @throws GeneralCryptoLibException
     *             if {@code SchnorrProofVerifier} was initialized by the
     *             invalid parameters.
     */
    public boolean verify() throws GeneralCryptoLibException {

        PhiFunctionSchnorr<T> phiFunctionSchnorr =
            new PhiFunctionSchnorr<>(_group, buildBaseElementsList());

        Verifier<T, E> verifier =
            new Verifier<>(_group, phiFunctionSchnorr,
                _configMessageDigestAlgorithmAndProvider,
                _configProofHashCharset);

        return verifier.verify(buildListPublicValues(), _proof,
            buildDataString());
    }

    private List<E> buildBaseElementsList() {

        List<E> baseElements = new ArrayList<>();
        baseElements.add(_group.getGenerator());
        return baseElements;
    }

    private List<E> buildListPublicValues() {

        List<E> exponentiatedElements = new ArrayList<>();
        exponentiatedElements.add(_exponentiatedElement);
        return exponentiatedElements;
    }

    private String buildDataString() {

        return "SchnorrProof:VoterID=" + _voterID + "ElectionEventID="
            + _electionEventID;
    }
}
