/*
 * 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
 */
cryptolib.modules.asymmetric = cryptolib.modules.asymmetric || {};

cryptolib.modules.asymmetric.service = function(box) {
  'use strict';

  box.asymmetric = box.asymmetric || {};
  /**
   * A module that holds certificates functionalities.
   * @exports asymmetric/service
   */
  box.asymmetric.service = {};

  var keypairGeneratorFactory, signerFactory, xmlSignerFactory,
      cipherFactory;

  cryptolib(
      'asymmetric.signer', 'asymmetric.xmlsigner', 'asymmetric.keypair',
      'asymmetric.cipher', 'commons.exceptions', function(box) {
        keypairGeneratorFactory =
            new box.asymmetric.keypair.factory.KeyPairGeneratorFactory();
        signerFactory = new box.asymmetric.signer.factory.SignerFactory();
        xmlSignerFactory =
            new box.asymmetric.xmlsigner.factory.XmlSignerFactory();
        cipherFactory =
            new box.asymmetric.cipher.factory.AsymmetricCipherFactory();
      });

  /**
   * Generates a {@link asymmetric/keypair.KeyPair} to be used for encrypt data.
   * @function
   * @returns {asymmetric/keypair.KeyPair} it can be used for encrypt data.
   */
  box.asymmetric.service.getKeyPairForEncryption = function() {
    var cryptoKeyPairGenerator =
        keypairGeneratorFactory.getEncryptionCryptoKeyPairGenerator();
    return cryptoKeyPairGenerator.generate();
  };

  /**
   * Encrypts the given plain text using the given
   * public key.
   * @function
   * @param publicKeyPem
   *            {String} public key, as string in PEM format.
   * @param dataBase64
   *            {String} data to encrypt, as a string in Base64 encoded
   *            format.
   * @return encrypted data in Base64 encoded format.
   */
  box.asymmetric.service.encrypt = function(publicKeyPem, dataBase64) {
    var cipher = cipherFactory.getCryptoAsymmetricCipher();
    return cipher.encrypt(publicKeyPem, dataBase64);
  };

  /**
   * Decrypts the given cipher text with the given
   * private key.
   * @function
   * @param privateKeyPem
   *            {String} private key, as string in PEM format.
   * @param encryptedDataBase64
   *            {String} data to decrypt, as a string in Base64 encoded
   *            format.
   * @return a string in Base64 encoded format.
   */
  box.asymmetric.service.decrypt = function(
      privateKeyPem, encryptedDataBase64) {
    var cipher = cipherFactory.getCryptoAsymmetricCipher();
    return cipher.decrypt(privateKeyPem, encryptedDataBase64);
  };

  /**
   * Signs the given message using the given private key.
   * @function
   * @param privateKeyPem
   *            {String} private key, as string in PEM format.
   * @param arrayDataBase64
   *            {String} data to sign, as an array of string in Base64 encoded
   *            format.
   * @return signature, in Base64 encoded format.
   */
  box.asymmetric.service.sign = function(privateKeyPem, ArrayDataBase64) {
    var cryptoSigner = signerFactory.getCryptoSigner();
    return cryptoSigner.sign(privateKeyPem, ArrayDataBase64);
  };

  /**
   * Verifies that the given signature is indeed the signature of the given
   * bytes, using the given public key.
   * @function
   * @param signatureB64
   *            {String} signature, as string in Base64 encoded format.
   * @param publicKeyPem
   *            {String} public key, as string in PEM format.
   * @param arrayDataBase64
   *            {String} data that was signed, as an array of string in Base64
   *            encoded format.
   *
   * @return boolean indicating whether signature verification was successful.
   */
  box.asymmetric.service.verifySignature = function(
      signatureBase64, publicKeyPem, arrayDataBase64) {
    var cryptoSigner = signerFactory.getCryptoSigner();
    return cryptoSigner.verify(signatureBase64, publicKeyPem, arrayDataBase64);
  };

  /**
   * Verifies the signature of some data that is in XML format.
   * @function
   * @param publicKey
   *            {Object} Public key.
   * @param signedXml
   *            {string} XML with selfcontained signature, to verify
   * @param signatureParentNode
   *            {string} Node where the signature is
   *
   * @return boolean indicating whether signature verification was successful.
   */
  box.asymmetric.service.verifyXmlSignature = function(
      publicKey, signedXml, signatureParentNode) {
    var cryptoXmlSigner = xmlSignerFactory.getCryptoXmlSigner();
    return cryptoXmlSigner.verify(publicKey, signedXml, signatureParentNode);
  };
};
