/*
 * 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.config.commands.ballotbox;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.certificates.cryptoapi.CryptoAPIX509Certificate;
import com.scytl.products.ov.commons.beans.EncryptionParameters;
import com.scytl.products.ov.constants.Constants;
import com.scytl.products.ov.datapacks.beans.ConfigurationInput;
import com.scytl.products.ov.datapacks.beans.CredentialProperties;
import com.scytl.products.ov.readers.ConfigurationInputReader;
import com.scytl.products.ov.utils.EncryptionParametersLoader;
import com.scytl.products.ov.utils.KeyStoreReader;
import com.scytl.products.ov.utils.X509CertificateLoader;

public class BallotBoxHolderInitializer {

    private final ConfigurationInputReader configurationInputReader;

    private final X509CertificateLoader x509CertificateLoader;

    private final KeyStoreReader keyStoreReader;

    private final EncryptionParametersLoader encryptionParametersLoader;

    public BallotBoxHolderInitializer(final ConfigurationInputReader configurationInputReader,
            final X509CertificateLoader x509CertificateLoader,
            final EncryptionParametersLoader encryptionParametersLoader, final KeyStoreReader keyStoreReader) {

    	this.configurationInputReader = configurationInputReader;
    	this.x509CertificateLoader = x509CertificateLoader;
    	this.encryptionParametersLoader = encryptionParametersLoader;
    	this.keyStoreReader = keyStoreReader;
    }

    public void init(final BallotBoxParametersHolder holder, final InputStream configurationInputStream)
            throws URISyntaxException, IOException, GeneralSecurityException, GeneralCryptoLibException {

        final ConfigurationInput configurationInput = getConfigurationInput(configurationInputStream);
        initFromConfigurationInput(holder, configurationInput);
    }

    public void init(final BallotBoxParametersHolder holder, final File configurationInputFile)
            throws URISyntaxException, IOException, GeneralSecurityException, GeneralCryptoLibException {

        try (InputStream is = Files.newInputStream(configurationInputFile.toPath())) {
            final ConfigurationInput configurationInput = getConfigurationInput(is);
            initFromConfigurationInput(holder, configurationInput);
        }
    }

    private void initFromConfigurationInput(final BallotBoxParametersHolder holder,
            final ConfigurationInput configurationInput)
            throws IOException, GeneralSecurityException, GeneralCryptoLibException {

        final CredentialProperties credentialPropertiesServicesCA =
            configurationInput.getConfigProperties().get(Constants.CONFIGURATION_SERVICES_CA_JSON_TAG);

        final CredentialProperties credentialPropertiesElectionCA =
            configurationInput.getConfigProperties().get(Constants.CONFIGURATION_ELECTION_CA_JSON_TAG);

        final String aliasPrivateKey =
            credentialPropertiesServicesCA.getAlias().get(Constants.CONFIGURATION_SERVICES_CA_PRIVATE_KEY_JSON_TAG);

        final String nameServicesCA = credentialPropertiesServicesCA.getName();

        final String nameElectionCA = credentialPropertiesElectionCA.getName();

        final String pemFileServicesCA = nameServicesCA + Constants.PEM;

        final String pemFileElectionCA = nameElectionCA + Constants.PEM;

        final Path absolutePath = holder.getOutputPath();
        final CryptoAPIX509Certificate servicesCACert =
            x509CertificateLoader.load(absolutePath.resolve(Constants.OFFLINE_DIRECTORY).resolve(pemFileServicesCA));

        final CryptoAPIX509Certificate electionCACert =
            x509CertificateLoader.load(absolutePath.resolve(Constants.OFFLINE_DIRECTORY).resolve(pemFileElectionCA));

        final Path servicesKeyStorePath =
            absolutePath.resolve(Constants.OFFLINE_DIRECTORY).resolve(Constants.SERVICES_SIGNER_SKS_FILENAME);
        final Path passwordPath = absolutePath.resolve(Constants.OFFLINE_DIRECTORY).resolve(Constants.PW_TXT);

        final PrivateKey servicesCAPrivateKey =
            keyStoreReader.getPrivateKey(servicesKeyStorePath, passwordPath, nameServicesCA, aliasPrivateKey);

        final CredentialProperties ballotBoxCredentialProperties = configurationInput.getBallotBox();

        // absolutePath points to election event folder. encryption params is
        // now inside
        final Path encParamsPath = absolutePath.resolve(Constants.ENCRYPTION_PARAMS_FILENAME);

        final EncryptionParameters encParams = encryptionParametersLoader.load(encParamsPath);

        holder.setServicesCAPrivateKey(servicesCAPrivateKey);
        holder.setBallotBoxCredentialProperties(ballotBoxCredentialProperties);
        holder.setEncryptionParameters(encParams);
        holder.setServicesCACert(servicesCACert);
        holder.setElectionCACert(electionCACert);
    }

    private ConfigurationInput getConfigurationInput(final InputStream configurationInputStream) throws IOException {
        return configurationInputReader.fromStreamToJava(configurationInputStream);
    }
}
