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

import org.apache.log4j.Appender;
import org.apache.log4j.Layout;
import org.apache.log4j.spi.ErrorHandler;
import org.apache.log4j.spi.Filter;
import org.apache.log4j.spi.LoggingEvent;

import java.security.PrivateKey;
import java.security.PublicKey;

/**
 * Implementation of {@link Appender} which wraps an instance of {@link SecureAppender} and defers
 * it's activation.
 *
 * <p>Clients use this class instead of {@link SecureAppender} in cases when the cipher and
 * signature private keys cannot be specified in the log4j configuration. In such cases the client
 * defines an instance of this class in log4j.xml, at runtime the system populates it's properties
 * and when the keys are available the client calls
 * {@link #activateOptions(PrivateKey, PrivateKey, PublicKey)} method.
 *
 * <p>Instances of this class are thread-safe.
 *
 * @author aakimov
 */
public class DeferredSecureAppender implements Appender {
  private final SecureAppender delegate;

  /**
   * Constructor.
   */
  public DeferredSecureAppender() {
    this(new SecureAppender());
  }

  /**
   * Constructor. For internal use only.
   *
   * @param delegate the delegate 
   */
  DeferredSecureAppender(SecureAppender delegate) {
    this.delegate = delegate;
  }

  /**
   * Activate options using the specified keys.
   *
   * @param signaturePrivateKey the signature private key
   * @param cipherPrivateKey the cipher private key
   * @param cipherPublicKey the cipher public key.
   */
  public void activateOptions(PrivateKey signaturePrivateKey, PrivateKey cipherPrivateKey,
      PublicKey cipherPublicKey) {
    synchronized (delegate) {
      delegate.setSignaturePrivateKey(signaturePrivateKey);
      delegate.setCipherPrivateKey(cipherPrivateKey);
      delegate.setCipherPublicKey(cipherPublicKey);
      delegate.activateOptions();
    }
  }

  @Override
  public void addFilter(Filter newFilter) {
    delegate.addFilter(newFilter);
  }

  @Override
  public void clearFilters() {
    delegate.clearFilters();
  }

  @Override
  public void close() {
    delegate.close();
  }

  @Override
  public void doAppend(LoggingEvent event) {
    delegate.doAppend(event);
  }

  /**
   * Returns the append option.
   * 
   * @return the append option.
   */
  public boolean getAppend() {
    return delegate.getAppend();
  }

  /**
   * Returns the buffer I/O option.
   * 
   * @return the buffer I/O option.
   */
  public boolean getBufferedIO() {
    return delegate.getBufferedIO();
  }

  /**
   * Returns the buffer size.
   * 
   * @return the buffer size.
   */
  public int getBufferSize() {
    return delegate.getBufferSize();
  }

  /**
   * Returns the cryptography provider class.
   *
   * @return the cryptography provider class.
   */
  public String getCryptographyProviderClass() {
    return delegate.getCryptographyProviderClass();
  }

  /**
   * Returns the encoding.
   * 
   * @return the encoding.
   */
  public String getEncoding() {
    return delegate.getEncoding();
  }

  @Override
  public ErrorHandler getErrorHandler() {
    return delegate.getErrorHandler();
  }

  @Override
  public Filter getFilter() {
    return delegate.getFilter();
  }

  @Override
  public Layout getLayout() {
    return delegate.getLayout();
  }

  /**
   * Returns the log file name policy name.
   *
   * @return the log file name policy name.
   */
  public String getLogFileNamePolicyName() {
    return delegate.getLogFileNamePolicyName();
  }

  @Override
  public String getName() {
    return delegate.getName();
  }

  /**
   * Returns the number of log lines.
   *
   * @return the number of log lines.
   */
  public int getNumberLogLines() {
    return delegate.getNumberLogLines();
  }

  public String getPattern() {
    return delegate.getPattern();
  }

  /**
   * Returns the timer log in milliseconds.
   *
   * @return the timer log in milliseconds.
   */
  public long getTimerLogMilliseconds() {
    return delegate.getTimerLogMilliseconds();
  }

  /**
   * Returns the triggering time.
   *
   * @return the triggering time.
   */
  public long getTriggeringTime() {
    return delegate.getTriggeringTime();
  }

  /**
   * Returns the verify pattern.
   *
   * @return the verify pattern.
   */
  public String getVerifyPattern() {
    return delegate.getVerifyPattern();
  }

  @Override
  public boolean requiresLayout() {
    return delegate.requiresLayout();
  }

  /**
   * Sets the append option.
   * 
   * @param append the append option.
   */
  public void setAppend(boolean append) {
    delegate.setAppend(append);
  }

  /**
   * Sets the buffered I/O option.
   * 
   * @param bufferedIO the buffered I/O option.
   */
  public void setBufferedIO(boolean bufferedIO) {
    delegate.setBufferedIO(bufferedIO);
  }

  /**
   * Sets the buffer size.
   * 
   * @param bufferSize the buffer size.
   */
  public void setBufferSize(int bufferSize) {
    delegate.setBufferSize(bufferSize);
  }

  /**
   * Sets the cipher cryptography provider class.
   *
   * @param cryptographyProviderClass the cipher cryptography provider class.
   */
  public void setCryptographyProviderClass(String cryptographyProviderClass) {
    delegate.setCryptographyProviderClass(cryptographyProviderClass);
  }

  /**
   * Sets the encoding.
   * 
   * @param encoding the encoding.
   */
  public void setEncoding(String encoding) {
    delegate.setEncoding(encoding);
  }

  @Override
  public void setErrorHandler(ErrorHandler errorHandler) {
    delegate.setErrorHandler(errorHandler);
  }

  /**
   * Sets the file.
   * 
   * @param file the file
   */
  public void setFile(String file) {
    delegate.setFile(file);
  }

  @Override
  public void setLayout(Layout layout) {
    delegate.setLayout(layout);
  }

  /**
   * Sets the log file name policy name.
   *
   * @param logFileNamePolicyName the log file name policy name.
   */
  public void setLogFileNamePolicyName(String logFileNamePolicyName) {
    delegate.setLogFileNamePolicyName(logFileNamePolicyName);
  }

  @Override
  public void setName(String name) {
    delegate.setName(name);
  }

  /**
   * Sets the number of lines to log a secure checkpoint entry.
   *
   * @param numberLogLines the number of lines to log a secure checkpoint entry.
   */
  public void setNumberLogLines(int numberLogLines) {
    delegate.setNumberLogLines(numberLogLines);
  }

  /**
   * Sets the pattern.
   *
   * @param pattern The pattern to set.
   */
  public void setPattern(String pattern) {
    delegate.setPattern(pattern);
  }

  /**
   * Sets the milliseconds to log a secure checkpoint entry.
   *
   * @param timerLogMilliseconds the milliseconds to log a secure checkpoint entry.
   */
  public void setTimerLogMilliseconds(long timerLogMilliseconds) {
    delegate.setTimerLogMilliseconds(timerLogMilliseconds);
  }

  /**
   * Sets the triggering time.
   *
   * @param the triggering time.
   */
  public void setTriggeringTime(long triggeringTime) {
    delegate.setTriggeringTime(triggeringTime);
  }

  /**
   * Sets the verification pattern.
   *
   * @param verifyPattern the verification pattern..
   */
  public void setVerifyPattern(String verifyPattern) {
    delegate.setVerifyPattern(verifyPattern);
  }
}


