/*
 * 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 CommonTestData = require('./common-data');
var elGamal = require('scytl-elgamal');

module.exports = SimplePlaintextEqualityProofTestData;

/**
 * Provides the data needed by the simple plaintext equality zero-knowledge
 * proof of knowledge unit tests.
 */
function SimplePlaintextEqualityProofTestData() {
  var NUM_SIMPLE_PLAINTEXT_ELEMENTS = 4;
  var SIMPLE_PLAINTEXT_EQUALITY_PROOF_STRING_DATA =
      'Test Simple Plaintext Equality Proof Auxilary Data';
  var OTHER_SIMPLE_PLAINTEXT_EQUALITY_PROOF_STRING_DATA =
      SIMPLE_PLAINTEXT_EQUALITY_PROOF_STRING_DATA + '0';
  var NUM_SIMPLE_PLAINTEXT_EQUALITY_PROOF_PROGRESS_CHECKS =
      NUM_SIMPLE_PLAINTEXT_ELEMENTS + 1;

  var elGamalEncrypter = elGamal.newService().newEncrypter();

  var commonTestData = new CommonTestData();
  var group_ = commonTestData.getGroup();
  var anotherGroup_ = commonTestData.getAnotherGroup();

  var publicKey =
      commonTestData.generateKeyPair(group_, NUM_SIMPLE_PLAINTEXT_ELEMENTS)
          .publicKey;
  var primaryPublicKey_ = commonTestData.getSubPublicKey(
      group_, publicKey, 0, (NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2));
  var secondaryPublicKey_ = commonTestData.getSubPublicKey(
      group_, publicKey, (NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2),
      NUM_SIMPLE_PLAINTEXT_ELEMENTS);
  var anotherPrimaryPublicKey_;
  do {
    anotherPrimaryPublicKey_ =
        commonTestData
            .generateKeyPair(group_, NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2)
            .publicKey;
  } while (
      anotherPrimaryPublicKey_.elements.equals(primaryPublicKey_.elements));
  var anotherSecondaryPublicKey_;
  do {
    anotherSecondaryPublicKey_ =
        commonTestData
            .generateKeyPair(group_, NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2)
            .publicKey;
  } while (
      anotherSecondaryPublicKey_.elements.equals(secondaryPublicKey_.elements));
  var primaryPublicKeyWithLessElements_ = commonTestData.getSubPublicKey(
      group_, publicKey, 1, (NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2));
  var secondaryPublicKeyWithLessElements_ = commonTestData.getSubPublicKey(
      group_, publicKey, ((NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2) + 1),
      NUM_SIMPLE_PLAINTEXT_ELEMENTS);
  var publicKeyFromAnotherGroup =
      commonTestData
          .generateKeyPair(anotherGroup_, NUM_SIMPLE_PLAINTEXT_ELEMENTS)
          .publicKey;
  var primaryPublicKeyFromAnotherGroup_ = commonTestData.getSubPublicKey(
      anotherGroup_, publicKeyFromAnotherGroup, 0,
      (NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2));
  var secondaryPublicKeyFromAnotherGroup_ = commonTestData.getSubPublicKey(
      anotherGroup_, publicKeyFromAnotherGroup,
      (NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2), NUM_SIMPLE_PLAINTEXT_ELEMENTS);

  var simplePlaintext_ = commonTestData.generateSimplePlaintext(
      group_, NUM_SIMPLE_PLAINTEXT_ELEMENTS);
  var simplePlaintextFromAnotherGroup = commonTestData.generateSimplePlaintext(
      anotherGroup_, NUM_SIMPLE_PLAINTEXT_ELEMENTS);

  var encryptedElements = elGamalEncrypter.init(publicKey).encrypt(
      simplePlaintext_, {saveSecret: true});
  var primaryEncryptedElements_ = commonTestData.getSubEncryptedElements(
      encryptedElements, 0, (NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2));
  var secondaryEncryptedElements_ = commonTestData.getSubEncryptedElements(
      encryptedElements, (NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2),
      NUM_SIMPLE_PLAINTEXT_ELEMENTS);
  var subPlaintext;
  var otherPrimaryEncryptedElements_;
  do {
    subPlaintext = commonTestData.generateSimplePlaintext(
        group_, (NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2));
    otherPrimaryEncryptedElements_ =
        elGamalEncrypter.init(primaryPublicKey_).encrypt(subPlaintext, {
          saveSecret: true
        });
  } while (subPlaintext.equals(
      simplePlaintext_.slice(0, (NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2))));
  var otherSecondaryEncryptedElements_;
  do {
    subPlaintext = commonTestData.generateSimplePlaintext(
        group_, (NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2));
    otherSecondaryEncryptedElements_ =
        elGamalEncrypter.init(secondaryPublicKey_).encrypt(subPlaintext, {
          saveSecret: true
        });
  } while (subPlaintext.equals(simplePlaintext_.slice(
      (NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2), NUM_SIMPLE_PLAINTEXT_ELEMENTS)));
  var primaryEncryptedElementsWithLessElements_ =
      commonTestData.getSubEncryptedElements(
          encryptedElements, 1, (NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2));
  var secondaryEncryptedElementsWithLessElements_ =
      commonTestData.getSubEncryptedElements(
          encryptedElements, ((NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2) + 1),
          NUM_SIMPLE_PLAINTEXT_ELEMENTS);
  encryptedElements =
      elGamalEncrypter.init(publicKeyFromAnotherGroup)
          .encrypt(simplePlaintextFromAnotherGroup, {saveSecret: true});
  var primaryEncryptedElementsFromAnotherGroup_ =
      commonTestData.getSubEncryptedElements(
          encryptedElements, 0, (NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2));
  var secondaryEncryptedElementsFromAnotherGroup_ =
      commonTestData.getSubEncryptedElements(
          encryptedElements, (NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2),
          NUM_SIMPLE_PLAINTEXT_ELEMENTS);

  var nonSimplePlaintext_ = commonTestData.generateNonSimplePlaintext(
      group_, NUM_SIMPLE_PLAINTEXT_ELEMENTS);
  encryptedElements = elGamalEncrypter.init(publicKey).encrypt(
      nonSimplePlaintext_, {saveSecret: true});
  var primaryEncryptedElementsForNonSimplePlaintext_ =
      commonTestData.getSubEncryptedElements(
          encryptedElements, 0, (NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2));
  var secondaryEncryptedElementsForNonSimplePlaintext_ =
      commonTestData.getSubEncryptedElements(
          encryptedElements, (NUM_SIMPLE_PLAINTEXT_ELEMENTS / 2),
          NUM_SIMPLE_PLAINTEXT_ELEMENTS);

  this.getGroup = function() {
    return group_;
  };

  this.getAnotherGroup = function() {
    return anotherGroup_;
  };

  this.getPrimaryPublicKey = function() {
    return primaryPublicKey_;
  };

  this.getSecondaryPublicKey = function() {
    return secondaryPublicKey_;
  };

  this.getAnotherPrimaryPublicKey = function() {
    return anotherPrimaryPublicKey_;
  };

  this.getAnotherSecondaryPublicKey = function() {
    return anotherSecondaryPublicKey_;
  };

  this.getPrimaryPublicKeyWithLessElements = function() {
    return primaryPublicKeyWithLessElements_;
  };

  this.getSecondaryPublicKeyWithLessElements = function() {
    return secondaryPublicKeyWithLessElements_;
  };

  this.getPrimaryPublicKeyFromAnotherGroup = function() {
    return primaryPublicKeyFromAnotherGroup_;
  };

  this.getSecondaryPublicKeyFromAnotherGroup = function() {
    return secondaryPublicKeyFromAnotherGroup_;
  };

  this.getPrimaryEncryptedElements = function() {
    return primaryEncryptedElements_;
  };

  this.getSecondaryEncryptedElements = function() {
    return secondaryEncryptedElements_;
  };

  this.getOtherPrimaryEncryptedElements = function() {
    return otherPrimaryEncryptedElements_;
  };

  this.getOtherSecondaryEncryptedElements = function() {
    return otherSecondaryEncryptedElements_;
  };

  this.getPrimaryEncryptedElementsWithLessElements = function() {
    return primaryEncryptedElementsWithLessElements_;
  };

  this.getSecondaryEncryptedElementsWithLessElements = function() {
    return secondaryEncryptedElementsWithLessElements_;
  };

  this.getPrimaryEncryptedElementsFromAnotherGroup = function() {
    return primaryEncryptedElementsFromAnotherGroup_;
  };

  this.getSecondaryEncryptedElementsFromAnotherGroup = function() {
    return secondaryEncryptedElementsFromAnotherGroup_;
  };

  this.getStringData = function() {
    return SIMPLE_PLAINTEXT_EQUALITY_PROOF_STRING_DATA;
  };

  this.getOtherStringData = function() {
    return OTHER_SIMPLE_PLAINTEXT_EQUALITY_PROOF_STRING_DATA;
  };

  this.getNonSimplePlaintext = function() {
    return nonSimplePlaintext_;
  };

  this.getPrimaryEncryptedElementsForNonSimplePlaintext = function() {
    return primaryEncryptedElementsForNonSimplePlaintext_;
  };

  this.getSecondaryEncryptedElementsForNonSimplePlaintext = function() {
    return secondaryEncryptedElementsForNonSimplePlaintext_;
  };

  this.getNumProgressChecks = function() {
    return NUM_SIMPLE_PLAINTEXT_EQUALITY_PROOF_PROGRESS_CHECKS;
  };
}
