/*
 * 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
 */
/* global OV */
/* global CL */
/* global forge */
/* jshint maxlen: 6666 */

module.exports = (function() {

    'use strict';

    var computeValues = function(encryptionParams, randomFactory, key) {
        var rve = randomFactory.getCryptoRandomInteger().nextRandomByBits(256);
        var C0 = encryptionParams.g.modPow(rve, encryptionParams.p);
        var preC1 = key.getGroupElementsArray().map(function(k) {
            return k.getElementValue().modPow(rve, encryptionParams.p);
        });

        return {
            rve: (new CL.commons.mathematical.Exponent(encryptionParams.q, rve)).stringify(),
            C0: (new CL.commons.mathematical.ZpGroupElement(C0, encryptionParams.p, encryptionParams.q)).stringify(),
            preC1: preC1.map(function(x) {
                return (new CL.commons.mathematical.ZpGroupElement(x, encryptionParams.p, encryptionParams.q)).stringify();
            })
        };

    };
	
	// Precompute EG encrypter values

    var precomputeEncryptionValues = function(serializedEncParams) {

        var encryptionParams = new OV.model.EncryptionParams({
            serializedP: serializedEncParams.serializedP,
            serializedG: serializedEncParams.serializedG,
            serializedOptionsEncryptionKey: serializedEncParams.serializedOptionsEncryptionKey,
            serializedChoiceCodesEncryptionKey: serializedEncParams.serializedChoiceCodesEncryptionKey
        });

        var randomFactory = new CL.primitives.securerandom.factory.SecureRandomFactory();
        return {
            options: computeValues(encryptionParams, randomFactory, encryptionParams.optionsEncryptionKey),
            choicecodes: computeValues(encryptionParams, randomFactory, encryptionParams.choiceCodesEncryptionKey)
        };

    };

    var deserializeEncryptionValues = function(serializedEncryptionValues) {

        var deserializeValues = function(serializedValues) {
            return new CL.homomorphic.cipher.ElGamalEncrypterValues(
                CL.commons.mathematical.groupUtils.deserializeExponent(serializedValues.rve),
                CL.commons.mathematical.groupUtils.deserializeGroupElement(serializedValues.C0),
                serializedValues.preC1.map(function(v) {
                    return CL.commons.mathematical.groupUtils.deserializeGroupElement(v);
                })
            );
        };

        return {
            options: deserializeValues(serializedEncryptionValues.options),
            choicecodes: deserializeValues(serializedEncryptionValues.choicecodes)
        };
    };

    return {
        deserializeEncryptionValues: deserializeEncryptionValues,
        precomputeEncryptionValues: precomputeEncryptionValues
    };

})();
