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

import com.scytl.products.ov.commons.infrastructure.remote.client.NodeIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Paths;
import java.util.Properties;

/**
 * @author jbarrio
 * @date 15/12/16
 *
 * Copyright (C) 2016 Scytl Secure Electronic Voting SA
 *
 * All rights reserved.
 */
abstract class AbstractKeystorePasswordsReader implements KeystorePasswordsReader {

	protected static final Logger LOG = LoggerFactory.getLogger("std");
	
	private static final String INTERNAL_PW_PATH = "/";
	private static final String EXTERNAL_PW_PATH =
			Paths.get( System.getProperty("user.home"),"certificates").toString();

	private static final String FILENAME_SUFFIX = ".properties";

	protected boolean destroyed;
	protected final KeystoreResources resources;
	protected final String passwordsPath;

	protected AbstractKeystorePasswordsReader(final KeystoreResources resources, final String filenamePrefix, final NodeIdentifier nodeIdentifier) {
		this.resources = resources;
		final String tempPasswordsPath;
		if (this.resources.getKeystoreProperties().isExternalPasswordsFile()) {
			tempPasswordsPath = EXTERNAL_PW_PATH;
		} else {
			tempPasswordsPath = INTERNAL_PW_PATH;
		}
		passwordsPath = tempPasswordsPath + filenamePrefix
			+ (nodeIdentifier == null ? "" : "." + nodeIdentifier.getAlias())
			+ FILENAME_SUFFIX
		;
	}

	protected KeystorePasswords getKeystorePasswordsInstance(final Properties properties) throws IOException {
		return KeystorePasswordsImpl.getInstance( properties );
	}


	/**
	 * Reads the passwords associated with the node this object was created for, without destroying the object.
	 *
	 * @return Passwords for the node this object was created for, if found; null if read error, not found, or destroyed.
	 */
	@Override
	public KeystorePasswords read() {
		if (this.destroyed) {
			final String errorMsg = "Object is destroyed";
			LOG.info( errorMsg );
			return null;
		} else {
			final String resourcePath = this.passwordsPath;
			try (final InputStream inputStream = this.resources.getResourceAsStream( resourcePath )) {
				if (inputStream == null) {
					final String errorMsg = "Could not locate keystore passwords at " + resourcePath;
					LOG.info( errorMsg );
					return null;
				} else {
					final Properties properties = new Properties();
					properties.load( inputStream );
					return this.getKeystorePasswordsInstance( properties );
				}
			} catch (final IOException ioE ) {
				LOG.error("Error while trying to read keystore passwords from {}: {}", resourcePath, ioE.getMessage(),
						ioE);
				return null;
			}
		}
	}

	@Override
	public boolean isDestroyed() {
		return this.destroyed;
	}

}
