/*
 * 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.commons.crypto;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.api.scytl.keystore.ScytlKeyStoreServiceAPI;
import com.scytl.cryptolib.scytl.keystore.cryptoapi.CryptoAPIScytlKeyStore;
import com.scytl.products.ov.commons.beans.exceptions.ResourceNotFoundException;
import com.scytl.products.ov.commons.beans.validation.CryptographicOperationException;

/**
 * Generates cryptographic keystore instances
 */
public class KeystoreOpener {

	private final ScytlKeyStoreServiceAPI storesService;

	private final KeystoreRepository keystoreRepository;

	private final PasswordRepository passwordRepository;

	/**
	 * @param storesService a cryptographic keystore service. Thread safety of the new keystore opener will depend on
	 *        whether this keystore service is thread safe or not.
	 * @param keystoreRepository a repository used to locate the keystore contents
	 * @param passwordRepository a repository used to locate the keystore password
	 */
	public KeystoreOpener(ScytlKeyStoreServiceAPI storesService, KeystoreRepository keystoreRepository,
			PasswordRepository passwordRepository) {
		this.storesService = storesService;
		this.keystoreRepository = keystoreRepository;
		this.passwordRepository = passwordRepository;
	}

	/**
	 * Search, open and create an instance for the keystore identified by this tenant id, election event id and alias.
	 * 
	 * @param tenant the tenant identifier.
	 * @param eeid the election event identifier.
	 * @param alias the keystore alias.
	 * @return a keystore instance.
	 * @throws CryptographicOperationException if an error occurs during the keystore loading process.
	 * @throws ResourceNotFoundException if the keystore for this tenant id, election event id and alias can not be found.
	 */
	public CryptoAPIScytlKeyStore openForTenantEEIDAlias(String tenant, String eeid, String alias)
			throws CryptographicOperationException, ResourceNotFoundException {

		String keystoreJson = keystoreRepository.getJsonByTenantEEID(tenant, eeid);
		String password = passwordRepository.getByTenantEEIDAlias(tenant, eeid, alias);

		try (InputStream inputStream = new ByteArrayInputStream(keystoreJson.getBytes(StandardCharsets.UTF_8))) {

			char[] passwordAsCharArray = password.toCharArray();
			KeyStore.PasswordProtection passwordProtection = new KeyStore.PasswordProtection(passwordAsCharArray);

			return storesService.loadKeyStoreFromJSON(inputStream, passwordProtection);

		} catch (IOException | GeneralCryptoLibException e) {
			throw new CryptographicOperationException("Error opening a keystore: ", e);
		}
	}
}
