/*
 * 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
 */
/* jshint node:true */
'use strict';

var ExponentiationProofTestData = require('../data/exponentiation-proof-data');
var ProgressMeterTestData = require('../data/progress-meter-data');
var ValidationTestData = require('../data/validation-data');
var zkProof = require('../../lib/index');

describe('The zero-knowledge proof module should be able to ...', function() {
  var proofService_;

  var group_;
  var anotherGroup_;
  var secret_;
  var secretFromAnotherGroup_;
  var baseElements_;
  var lessBaseElements_;
  var baseElementsFromAnotherGroup_;
  var exponentiatedElements_;
  var tooManyExponentiatedElements_;
  var exponentiatedElementsFromAnotherGroup_;
  var callback_;
  var nonObject_;
  var emptyObject_;
  var nonNumber_;
  var nonPositiveNumber_;
  var nonString_;
  var nonArray_;
  var emptyArray_;
  var nonObjectArray_;
  var nonFunction_;
  var nonAuxiliaryData_;
  var nonProofObject_;
  var proofHandler_;
  var proof_;

  beforeAll(function() {
    proofService_ = zkProof.newService();

    var testData = new ExponentiationProofTestData();
    group_ = testData.getGroup();
    anotherGroup_ = testData.getAnotherGroup();
    secret_ = testData.getSecret();
    secretFromAnotherGroup_ = testData.getSecretFromAnotherGroup();
    baseElements_ = testData.getBaseElements();
    lessBaseElements_ = testData.getLessBaseElements();
    baseElementsFromAnotherGroup_ = testData.getBaseElementsFromAnotherGroup();
    exponentiatedElements_ = testData.getExponentiatedElements();
    exponentiatedElementsFromAnotherGroup_ =
        testData.getExponentiatedElementsFromAnotherGroup();
    tooManyExponentiatedElements_ = testData.getTooManyExponentiatedElements();

    var progressMeterTestData = new ProgressMeterTestData();
    callback_ = progressMeterTestData.progressCallback;

    var validationTestData = new ValidationTestData();
    nonObject_ = validationTestData.getNonObject();
    emptyObject_ = validationTestData.getEmptyObject();
    nonNumber_ = validationTestData.getNonNumber();
    nonPositiveNumber_ = validationTestData.getNonPositiveNumber();
    nonString_ = validationTestData.getNonString();
    nonArray_ = validationTestData.getNonArray();
    emptyArray_ = validationTestData.getEmptyArray();
    nonObjectArray_ = validationTestData.getNonObjectArray();
    nonFunction_ = validationTestData.getNonFunction();
    nonAuxiliaryData_ = validationTestData.getNonAuxiliaryData();
    nonProofObject_ = validationTestData.getNonProofObject();

    proofHandler_ =
        proofService_.newExponentiationProofHandler(group_).init(baseElements_);
    proof_ = proofHandler_.generate(secret_, exponentiatedElements_);
  });

  beforeEach(function() {
    proofHandler_ =
        proofService_.newExponentiationProofHandler(group_).init(baseElements_);
  });

  describe('create a zero-knowledge proof service that should be able to ..', function() {
    describe('create an exponentiation proof handler that should be able to', function() {
      it('throw an error when being created, using invalid input data',
         function() {
           expect(function() {
             proofService_.newExponentiationProofHandler();
           }).toThrow();

           expect(function() {
             proofService_.newExponentiationProofHandler(undefined);
           }).toThrow();

           expect(function() {
             proofService_.newExponentiationProofHandler(null);
           }).toThrow();

           expect(function() {
             proofService_.newExponentiationProofHandler(nonObject_);
           }).toThrow();

           expect(function() {
             proofService_.newExponentiationProofHandler(emptyObject_);
           }).toThrow();
         });

      it('throw an error when being initialized, using invalid input data',
         function() {
           expect(function() {
             proofHandler_.init(undefined);
           }).toThrow();

           expect(function() {
             proofHandler_.init(null);
           }).toThrow();

           expect(function() {
             proofHandler_.init(nonArray_);
           }).toThrow();

           expect(function() {
             proofHandler_.init(emptyArray_);
           }).toThrow();

           expect(function() {
             proofHandler_.init(nonObjectArray_);
           }).toThrow();

           expect(function() {
             proofHandler_.init(baseElementsFromAnotherGroup_);
           }).toThrow();
         });

      it('throw an error when generating an exponentiation proof, using an invalid secret',
         function() {
           expect(function() {
             proofHandler_.generate(undefined, exponentiatedElements_);
           }).toThrow();

           expect(function() {
             proofHandler_.generate(null, exponentiatedElements_);
           }).toThrow();

           expect(function() {
             proofHandler_.generate(nonObject_, exponentiatedElements_);
           }).toThrow();

           expect(function() {
             proofHandler_.generate(emptyObject_, exponentiatedElements_);
           }).toThrow();

           expect(function() {
             proofHandler_.generate(
                 secretFromAnotherGroup_, exponentiatedElements_);
           }).toThrow();
         });

      it('throw an error when generating an exponentiation proof, using invalid exponentiated elements',
         function() {
           expect(function() {
             proofHandler_.generate(secret_, undefined);
           }).toThrow();

           expect(function() {
             proofHandler_.generate(secret_, null);
           }).toThrow();

           expect(function() {
             proofHandler_.generate(secret_, nonArray_);
           }).toThrow();

           expect(function() {
             proofHandler_.generate(secret_, emptyArray_);
           }).toThrow();

           expect(function() {
             proofHandler_.generate(secret_, nonObjectArray_);
           }).toThrow();

           expect(function() {
             proofHandler_.generate(secret_, tooManyExponentiatedElements_);
           }).toThrow();

           expect(function() {
             proofHandler_.generate(
                 secret_, exponentiatedElementsFromAnotherGroup_);
           }).toThrow();
         });

      it('throw an error when generating a plaintext proof, using invalid optional data',
         function() {
           expect(function() {
             proofHandler_.generate(
                 secret_, exponentiatedElements_, {data: nonAuxiliaryData_});
           }).toThrow();

           expect(function() {
             proofHandler_.generate(
                 secret_, exponentiatedElements_, {preComputation: nonObject_});
           }).toThrow();

           expect(function() {
             proofHandler_.generate(
                 secret_, exponentiatedElements_,
                 {preComputation: nonProofObject_});
           }).toThrow();
         });

      it('throw an error when verifying an exponentiation proof, using an invalid proof',
         function() {
           expect(function() {
             proofHandler_.verify(undefined, exponentiatedElements_);
           }).toThrow();

           expect(function() {
             proofHandler_.verify(null, exponentiatedElements_);
           }).toThrow();

           expect(function() {
             proofHandler_.verify(nonProofObject_, exponentiatedElements_);
           }).toThrow();
         });

      it('throw an error when verifying an exponentiation proof, using invalid exponentiated elements',
         function() {
           expect(function() {
             proofHandler_.verify(proof_, undefined);
           }).toThrow();

           expect(function() {
             proofHandler_.verify(proof_, null);
           }).toThrow();

           expect(function() {
             proofHandler_.verify(proof_, nonArray_);
           }).toThrow();

           expect(function() {
             proofHandler_.verify(proof_, emptyArray_);
           }).toThrow();

           expect(function() {
             proofHandler_.verify(proof_, nonObjectArray_);
           }).toThrow();

           expect(function() {
             proofHandler_.verify(
                 proof_, exponentiatedElementsFromAnotherGroup_);
           }).toThrow();
         });

      it('throw an error when verifying an exponentiation proof, using invalid optional data',
         function() {
           expect(function() {
             proofHandler_.verify(
                 proof_, exponentiatedElements_, {data: nonAuxiliaryData_});
           }).toThrow();
         });

      it('throw an error when measuring exponentiation proof progress, using invalid input data',
         function() {
           expect(function() {
             proofHandler_.measureProgress();
           }).toThrow();

           expect(function() {
             proofHandler_.measureProgress(undefined);
           }).toThrow();

           expect(function() {
             proofHandler_.measureProgress(null);
           }).toThrow();

           expect(function() {
             proofHandler_.measureProgress(nonFunction_);
           }).toThrow();

           expect(function() {
             proofHandler_.measureProgress(callback_, null);
           }).toThrow();

           expect(function() {
             proofHandler_.measureProgress(callback_, nonNumber_);
           }).toThrow();

           expect(function() {
             proofHandler_.measureProgress(callback_, nonPositiveNumber_);
           }).toThrow();
         });
    });
  });
});
