/*
 * 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
 */
package com.scytl.products.ov.datapacks.generators;

import java.io.IOException;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.time.ZonedDateTime;
import java.util.Properties;

import org.apache.commons.configuration.ConfigurationException;

import com.scytl.cryptolib.api.asymmetric.AsymmetricServiceAPI;
import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.api.scytl.keystore.ScytlKeyStoreServiceAPI;
import com.scytl.cryptolib.certificates.cryptoapi.CryptoAPIX509Certificate;
import com.scytl.cryptolib.scytl.keystore.cryptoapi.CryptoAPIScytlKeyStore;
import com.scytl.cryptolib.securerandom.cryptoapi.CryptoAPIRandomString;
import com.scytl.products.oscore.logging.api.writer.LoggingWriter;
import com.scytl.products.ov.config.logs.Loggable;
import com.scytl.products.ov.datapacks.beans.CertificateParameters;
import com.scytl.products.ov.datapacks.beans.CredentialProperties;
import com.scytl.products.ov.datapacks.beans.InputDataPack;
import com.scytl.products.ov.datapacks.helpers.ReplacementsHolder;

public class CredentialDataPackGenerator {

	protected final AsymmetricServiceAPI asymmetricService;

	protected final X509CertificateGenerator certificateGenerator;

	protected final ScytlKeyStoreServiceAPI storesService;

	protected final CryptoAPIRandomString cryptoRandomString;

	@Loggable
	protected LoggingWriter logWriter;

	public CredentialDataPackGenerator(final AsymmetricServiceAPI asymmetricService,
			final CryptoAPIRandomString cryptoRandomString, final X509CertificateGenerator certificateGenerator,
			final ScytlKeyStoreServiceAPI storesService) {
		super();
		this.asymmetricService = asymmetricService;
		this.cryptoRandomString = cryptoRandomString;
		this.certificateGenerator = certificateGenerator;
		this.storesService = storesService;
	}

    protected CryptoAPIScytlKeyStore setPrivateKeyToKeystore(final CryptoAPIScytlKeyStore keystore, final String alias,
            final PrivateKey privateKey, final char[] keyStorePassword, final CryptoAPIX509Certificate... certs)
            throws GeneralCryptoLibException {

        final Certificate[] chain = new Certificate[certs.length];

        for (int i = 0; i < certs.length; i++) {
            chain[i] = certs[i].getCertificate();
        }

        keystore.setPrivateKeyEntry(alias, privateKey, keyStorePassword, chain);

        return keystore;
    }

    protected CryptoAPIX509Certificate createX509Certificate(final InputDataPack electionInputDataPack,
            final CertificateParameters certificateParameters, final KeyPair keyPair)
            throws GeneralCryptoLibException, ConfigurationException {

        final PublicKey publicKey = keyPair.getPublic();
        PrivateKey parentPrivateKey;

        if (electionInputDataPack.getParentKeyPair() == null) {
            parentPrivateKey = keyPair.getPrivate();
        } else {
            parentPrivateKey = electionInputDataPack.getParentKeyPair().getPrivate();
        }

		return certificateGenerator.generate(certificateParameters, publicKey, parentPrivateKey);
	}

    protected CertificateParameters getCertificateParameters(final CredentialProperties credentialProperties,
            final ZonedDateTime startDate, final ZonedDateTime endDate, final ReplacementsHolder replacementsHolder,
            final Properties certificateProperties) throws IOException, ConfigurationException {

        final CertificateParameters.Type type = credentialProperties.getCredentialType();
        final CertificateParametersLoader certificateParametersLoader =
            new CertificateParametersLoader(replacementsHolder);
        final CertificateParameters certificateParameters =
            certificateParametersLoader.load(certificateProperties, type);
        certificateParameters.setUserNotBefore(startDate);
        certificateParameters.setUserNotAfter(endDate);
        return certificateParameters;
    }
}
