/*
 * 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 SecureRandomService = require('./service');
var validator = require('./input-validator');

module.exports = {
  /**
   * Creates a new SecureRandomService object, which encapsulates a secure
   * random service.
   *
   * <p>
   * As soon as this service is instantiated, entropy collection will start.
   * The first time that a random generator created by the service is used,
   * the entropy collection will stop and the pseudo-random number generator
   * (PRNG) of the service will be initialized with the collected entropy.
   *
   * @function newService
   * @global
   * @param {Object}
   *            [options] An object containing optional arguments.
   * @param {Uint8Array}
   *            [options.prngSeed=Internally generated] The seed to initialize
   *            the PRNG.
   * @param {number}
   *            [options.maxEntropyCounter=256] The amount of entropy to
   *            accumulate before stopping collectors. It must be a positive
   * number.
   * @param {number}
   *            [options.hashUpdaterInterval=1000] The interval (in
   * milliseconds) at which entropy data is to be hashed. It must be a postive
   * number.
   * @param {Object}
   *            [options.windowObject=Built-in window object]
   *            The <code>window</code> object provided to the collectors.
   * @param {Object}
   *            [options.cryptoApi=Built-in cryptographic library]
   *            The cryptographic library supplied to the WebKit collector (if
   * the latter is being used).
   * @param {Object}
   *            [options.privateKeyData=Not used] The private key collector
   * data.
   * @param {string}
   *            options.privateKeyData.privateKey The private key, in PEM
   *            format.
   * @param {number}
   *            options.privateKeyData.pinEntropy The PIN entropy of the
   *            private key. It must be a positive number.
   * @param {boolean}
   *            [options.noDefaultCollectors=false] If <code>true</code>, no
   *            default entropy collectors are to be used.
   * @returns {SecureRandomService} The new SecureRandomService object.
   * @example <caption> How to initialize the PRNG of the service with a
   *          chosen seed</caption>
   *
   * var secureRandom = require('scytl-securerandom');
   *
   * var secureRandomService = secureRandom.newService({prngSeed: myPrngSeed});
   */
  newService: function(options) {
    checkData(options);

    return new SecureRandomService(options);
  }
};

function checkData(options) {
  options = options || {};

  if (typeof options.prngSeed !== 'undefined') {
    validator.checkIsInstanceOf(
        options.prngSeed, Uint8Array, 'Uint8Array', 'Seed to initialize PRNG');
  }

  if (typeof options.maxEntropyCounter !== 'undefined') {
    validator.checkIsPositiveNumber(
        options.maxEntropyCounter,
        'Amount of entropy to accumulate before stopping collectors');
  }

  if (typeof options.hashUpdaterInterval !== 'undefined') {
    validator.checkIsPositiveNumber(
        options.hashUpdaterInterval,
        'Interval (in milliseconds) at which entropy data is to be hashed');
  }

  if (typeof options.windowObject !== 'undefined') {
    validator.checkIsNotNull(
        options.windowObject, 'Window object provided to collectors');
    validator.checkIsObject(
        options.windowObject, 'Window object provided to collectors');
  }

  if (typeof options.cryptoApi !== 'undefined') {
    validator.checkIsNotNull(
        options.cryptoApi,
        'Cryptographic library supplied to WebKit collector');
    validator.checkIsObject(
        options.cryptoApi,
        'Cryptographic library supplied to WebKit collector');
  }

  if (typeof options.privateKeyData !== 'undefined') {
    validator.checkIsNonEmptyString(
        options.privateKeyData.privateKey, 'private key, in PEM format');
    validator.checkIsPositiveNumber(
        options.privateKeyData.pinEntropy, 'PIN entropy of private key.');
  }

  if (typeof options.noDefaultCollectors !== 'undefined') {
    validator.checkIsNotNull(
        options.noDefaultCollectors,
        'Flag to specify whether no default entropy collectors are to be used');
    validator.checkIsType(
        options.noDefaultCollectors, 'boolean',
        'Flag to specify whether no default entropy collectors are to be used');
  }
}
