/*
 * 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
 */
var exponentiationProofTest = {

  /**
   * Verifies an exponentiation zero knowledge proof of knowledge that was
   * generated using Java and checks if the verification was true.
   *
   * @param {String}
   *            zpSubgroupJson the Zp subgroup, in JSON format.
   * @param {String}
   *            baseElementsJson the base elements, in JSON format.
   * @param {String}
   *            exponentiatedElementsJson the exponentiated elements, in JSON
   *            format.
   * @param {String}
   *            proofJson the exponentiation zero knowledge proof, in JSON
   *            format.
   * @throws {Error}
   *             if the proof verification operation fails or the verification
   *             is false.
   */
  verify: function(
      zpSubgroupJson, baseElementsJson, exponentiatedElementsJson, proofJson,
      exponentJson) {

    'use strict';

    var errorData = {};
    errorData['Zp Subgroup (JSON format) [Java]'] = zpSubgroupJson;
    errorData['Base elements (JSON format) [Java]'] = baseElementsJson;
    errorData['Exponentiated base elements (JSON format) [Java]'] =
        exponentiatedElementsJson;
    errorData['Exponentiation zero knowledge proof (JSON format) [Java]'] =
        proofJson;

    try {
      cryptolib('commons.mathematical', 'proofs', 'proofs.service', function(box) {
        var zpSubgroup = box.commons.mathematical.groupUtils.deserializeGroup(
            zpSubgroupJson);

        var baseElements =
            testUtils.deserializeZpGroupElements(baseElementsJson);

        var exponentiatedElements =
            testUtils.deserializeZpGroupElements(exponentiatedElementsJson);

        var proof = box.proofs.utils.deserializeProof(proofJson);

        var verified = box.proofs.service.verifyExponentiationProof(
            exponentiatedElements, baseElements, proof, zpSubgroup);

        if (!verified) {
          throw 'Verification of exponentiation zero knowledge proof was false.';
        }
      });
    } catch (error) {
      throw testUtils.serializeError(error, errorData);
    }
  },

  /**
   * Generates an exponentiation zero knowledge proof of knowledge that will
   * be verified using Java.
   *
   * @param {String}
   *            zpSubgroupJson the Zp subgroup, in JSON format.
   * @param {String}
   *            baseElementsJson the base elements, in JSON format.
   * @param {String}
   *            exponentJson the exponent, in JSON format.
   * @param {String}
   *            exponentiatedElementsJson the exponentiated elements, in JSON
   *            format.
   * @param {String}
   *            preComputedValuesJson the pre-computed exponentiation proof
   *            values, in JSON format (if the pre-computation step was
   *            performed).
   * @returns {String} the generated exponentiation zero knowledge proof, in
   *          JSON format.
   * @throws {Error}
   *             if the proof generation operation fails.
   */
  generate: function(
      zpSubgroupJson, baseElementsJson, exponentJson, exponentiatedElementsJson,
      preComputedValuesJson) {

    'use strict';

    var errorData = {};
    errorData['Zp Subgroup (JSON format) [Java]'] = zpSubgroupJson;
    errorData['Base elements (JSON format) [Java]'] = baseElementsJson;
    errorData['Exponent (JSON format) [Java]'] = exponentJson;
    errorData['Exponentiated base elements (JSON format) [Java]'] =
        exponentiatedElementsJson;
    if (typeof preComputedValuesJson !== 'undefined') {
      errorData['Pre-computed exponentiation proof values (JSON format) [JS]'] =
          preComputedValuesJson;
    }

    try {
      var proofJson;
      cryptolib(
          'commons.mathematical', 'proofs', 'proofs.service', function(box) {
            var zpSubgroup =
                box.commons.mathematical.groupUtils.deserializeGroup(
                    zpSubgroupJson);

            var baseElements =
                testUtils.deserializeZpGroupElements(baseElementsJson);

            var exponent =
                box.commons.mathematical.groupUtils.deserializeExponent(
                    exponentJson);

            var exponentiatedElements =
                testUtils.deserializeZpGroupElements(exponentiatedElementsJson);

            var proof;
            if (typeof preComputedValuesJson !== 'undefined') {
              var preComputedValues =
                  box.proofs.utils.deserializeProofPreComputedValues(
                      preComputedValuesJson);
              proof = box.proofs.service.createExponentiationProof(
                  exponentiatedElements, baseElements, exponent, zpSubgroup,
                  preComputedValues);
            } else {
              proof = box.proofs.service.createExponentiationProof(
                  exponentiatedElements, baseElements, exponent, zpSubgroup);
            }

            proofJson = proof.stringify();
          });

      return proofJson;
    } catch (error) {
      throw testUtils.serializeError(error, errorData);
    }
  },

  /**
   * Generates pre-computed values that can be used to generate a
   * exponentiation zero knowledge proof of knowledge, using Java or
   * JavaScript.
   *
   * @param {String}
   *            zpSubgroupJson the Zp subgroup, in JSON format.
   * @param {String}
   *            baseElementsJson the base elements, in JSON format.
   * @returns {String} the pre-computed exponentiation proof values, in JSON
   *          format.
   * @throws {Error}
   *             if the pre-computed values generation operation fails.
   */
  generatePreComputedValues: function(zpSubgroupJson, baseElementsJson) {

    'use strict';

    var errorData = {};
    errorData['Zp Subgroup (JSON format) [Java]'] = zpSubgroupJson;
    errorData['Base elements (JSON format) [Java]'] = baseElementsJson;
    try {
      var preComputedValuesJson;
      cryptolib('commons.mathematical', 'proofs.service', function(box) {
        var zpSubgroup = box.commons.mathematical.groupUtils.deserializeGroup(
            zpSubgroupJson);

        var baseElements =
            testUtils.deserializeZpGroupElements(baseElementsJson);

        var preComputedValues =
            box.proofs.service.preComputeExponentiationProof(
                baseElements, zpSubgroup);

        preComputedValuesJson = preComputedValues.stringify();
      });

      return preComputedValuesJson;
    } catch (error) {
      throw testUtils.serializeError(error, errorData);
    }
  }
};