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

import com.scytl.slogger.SecureAppender;
import com.scytl.slogger.SecureLoggerException;
import com.scytl.slogger.crypto.SecureLoggerCryptographyProvider;
import com.scytl.slogger.processor.hmac.encrypted.signed.SignedEncryptedHMacEventProcessor;
import com.scytl.slogger.processor.secure.checkpoint.CheckpointEventProcessor;
import com.scytl.slogger.processor.signature.SignatureEventProcessor;

import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.LinkedList;
import java.util.List;

import javax.crypto.SecretKey;

/**
 * {@link LoggingEventProcessorList} Factory.
 */
public final class LoggingEventProcessorListFactory {

  /**
   * Private Constructor.
   */
  private LoggingEventProcessorListFactory() {}

  /**
   * Creates a logging event processor list.
   *
   * @param cipherPublicKey the cipher public key
   * @param signaturePrivateKey the signature provate key
   * @param numberLogLines the number of log lines
   * @param secureAppender the secure appender
   * @param timerLogMilliseconds the timer period in milliseconds
   * @param lastHMac the las HMAC
   * @param secretKey the secret key
   * @param cryptographyProvider The cryptography provider for the secure logger
   * @return the processor list
   * @throws SecureLoggerException failed to create the processor list.
   */

  public static LoggingEventProcessorList createLoggingEventProcessorList(
      final PublicKey cipherPublicKey, final PrivateKey signaturePrivateKey,
      final int numberLogLines, final SecureAppender secureAppender,
      final long timerLogMilliseconds, final byte[] lastHMac, final SecretKey secretKey,
      final SecureLoggerCryptographyProvider cryptographyProvider) throws SecureLoggerException {
    return createLoggingEventProcessorList(cipherPublicKey,
        new SignatureEventProcessor(signaturePrivateKey, cryptographyProvider), numberLogLines,
        secureAppender, timerLogMilliseconds, lastHMac, secretKey, cryptographyProvider);
  }

  /**
   * Creates a logging event procesor list with an specific signature event processor.
   *
   * @param cipherPublicKey the cipher public key
   * @param signatureEventProcessor the signature event processor
   * @param numberLogLines the number of log lines
   * @param secureAppender the secure appender
   * @param timerLogMilliseconds the timer period in milliseconds
   * @param lastHMac the las HMAC
   * @param secretKey the secret key
   * @param cryptographyProvider The cryptography provider for the secure logger
   * @return the processor list
   * @throws SecureLoggerException failed to create the processor list.
   */
  public static LoggingEventProcessorList createLoggingEventProcessorList(
      final PublicKey cipherPublicKey, final SignatureEventProcessor signatureEventProcessor,
      final int numberLogLines, final SecureAppender secureAppender,
      final long timerLogMilliseconds, final byte[] lastHMac, final SecretKey secretKey,
      final SecureLoggerCryptographyProvider cryptographyProvider) throws SecureLoggerException {
    try {
      SignedEncryptedHMacEventProcessor macEventProcessor =
          new SignedEncryptedHMacEventProcessor(lastHMac, secretKey, cipherPublicKey,
              signatureEventProcessor, cryptographyProvider, numberLogLines, timerLogMilliseconds);

      CheckpointEventProcessor checkpointEventProcessor = new CheckpointEventProcessor(
          macEventProcessor, secureAppender, numberLogLines, timerLogMilliseconds);

      List<LoggingEventProcessor> processorList = new LinkedList<>();
      processorList.add(new FileNameEventProcessor(secureAppender.getLogFileNamePolicy()));
      processorList.add(checkpointEventProcessor);
      final LoggingEventProcessorList loggingEventProcessor =
          new LoggingEventProcessorList(processorList);
      return loggingEventProcessor;
    } catch (GeneralSecurityException e) {
      throw new SecureLoggerException(e);
    }
  }
}
