/*
 * 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.channel.cc.commons.spring;

import java.io.IOException;
import java.nio.file.Paths;
import java.security.KeyManagementException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import com.scytl.products.ov.channel.cc.commons.keymanagement.NodeKeysActivator;
import com.scytl.products.ov.channel.cc.commons.slogger.SecureLoggerManager;
import com.scytl.slogger.SecureLoggerException;

/**
 * <p>
 * Basic abstract implementation of {@link Application} for the control
 * components.
 * <p>
 * A typical concrete subclass looks like the following: <pre>
 * <code>
 * &#64;Configuration
 * &#64;Import(...)
 * public class FooApplication extends AbstractControlComponentApplication {
 *     &#64;Autowire
 *     private FooEndpointManager endpointManager;
 * 
 *     public void main(String[] args) {
 *         Application.run(FooApplication.class, args);
 *     }
 *     
 *     &#64;Override
 *     protected activateMessageEndpoints() throws ApplicationException {
 *         try {
 *             endpointManager.activateMessageEndpoints();
 *         } catch (FooException e) {
 *             throw new ApplicationException("Failed to activate message endpoints.", e);
 *         }
 *     }
 *     
 *     &#64;Override
 *     protected deactivateMessageEndpoints() throws ApplicationException {
 *         try {
 *             endpointManager.deactivateMessageEndpoints();
 *         } catch (FooException e) {
 *             throw new ApplicationException("Failed to deactivate message endpoints.", e);
 *         }
 *     }
 * }
 * </code> </pre>
 */
public abstract class AbstractControlComponentApplication
        extends AbstractApplication {
    @Autowired
    private NodeKeysActivator nodeKeysActivator;

    @Autowired
    private SecureLoggerManager secureLoggerManager;

    @Value("${keys.keyStore}")
    private String keyStore;

    @Value("${keys.alias}")
    private String alias;

    @Value("${keys.passwordFile}")
    private String password;

    /**
     * Activates message endpoints.
     * 
     * @throws ApplicationException
     *             failed to activate message endpoints.
     */
    protected abstract void activateMessageEndpoints()
            throws ApplicationException;

    /**
     * Deactivates message endpoints.
     * 
     * @throws ApplicationException
     *             failed to deactivate message endpoints.
     */
    protected abstract void deactivateMessageEndpoints()
            throws ApplicationException;

    @Override
    protected final void doRun(String[] args) throws ApplicationException {
        activateNodeKeys();
        openSecureLog();
        try {
            activateMessageEndpoints();
            try {
                waitForShutdown();
            } finally {
                deactivateMessageEndpoints();
            }
        } finally {
            closeSecureLog();
        }
    }

    private void activateNodeKeys() throws ApplicationException {
        try {
            nodeKeysActivator.activateNodeKeys(Paths.get(keyStore), alias,
                Paths.get(password));
        } catch (KeyManagementException | IOException e) {
            throw new ApplicationException("Failed to activate node keys.",
                e);
        }
    }

    private void closeSecureLog() throws ApplicationException {
        try {
            secureLoggerManager.closeSecureLogger();
        } catch (SecureLoggerException e) {
            throw new ApplicationException("Failed to close secure log.",
                e);
        }
    }

    private void openSecureLog() throws ApplicationException {
        try {
            secureLoggerManager.openSecureLogger();
        } catch (SecureLoggerException e) {
            throw new ApplicationException("Failed to open secure log.",
                e);
        }
    }
}
