/*
 * 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.event.SecureLoggingEvent;
import com.scytl.slogger.event.SecurePatternLayout;

import java.util.LinkedList;
import java.util.List;

/**
 * Event Processor that encapsulates a list of LoggingEventProcessors. The processors are executed
 * depending on the order in the list. The output of each processor works as an input for the next
 * processor.
 */
public class LoggingEventProcessorList implements LoggingEventProcessor {

  private final List<LoggingEventProcessor> loggingEventProcessorList;

  /**
   * Constructor.
   *
   * @param loggingEventProcessorList the processor list.
   */
  public LoggingEventProcessorList(final List<LoggingEventProcessor> loggingEventProcessorList) {
    this.loggingEventProcessorList = loggingEventProcessorList;
  }

  @Override
  public void killProcessor() throws EventProcessorException {
    for (LoggingEventProcessor eventProcessor : loggingEventProcessorList) {
      eventProcessor.killProcessor();
    }
  }

  @Override
  public List<SecureLoggingEvent> processEvent(final SecureLoggingEvent loggingEvent,
      final SecurePatternLayout layout) throws EventProcessorException {
    return doProcessEvent(loggingEvent, layout, 0);
  }

  @Override
  public List<SecureLoggingEvent> startProcessor(final SecurePatternLayout layout)
      throws EventProcessorException {
    List<SecureLoggingEvent> resultList = new LinkedList<>();
    for (LoggingEventProcessor eventProcessor : loggingEventProcessorList) {
      resultList.addAll(eventProcessor.startProcessor(layout));
    }

    return resultList;
  }

  @Override
  public List<SecureLoggingEvent> stopProcessor(final SecurePatternLayout layout)
      throws EventProcessorException {
    List<SecureLoggingEvent> resultList = new LinkedList<>();
    for (LoggingEventProcessor eventProcessor : loggingEventProcessorList) {
      resultList.addAll(eventProcessor.stopProcessor(layout));
    }

    return resultList;
  }

  private List<SecureLoggingEvent> doProcessEvent(final SecureLoggingEvent loggingEvent,
      final SecurePatternLayout layout, final int index) throws EventProcessorException {

    if (index == loggingEventProcessorList.size()) {
      List<SecureLoggingEvent> resultlList = new LinkedList<>();
      resultlList.add(loggingEvent);

      return resultlList;
    }

    List<SecureLoggingEvent> processedEventList =
        loggingEventProcessorList.get(index).processEvent(loggingEvent, layout);

    List<SecureLoggingEvent> partialList = new LinkedList<>();
    if (processedEventList != null) {
      for (SecureLoggingEvent secureLoggingEvent : processedEventList) {
        partialList.addAll(doProcessEvent(secureLoggingEvent, layout, index + 1));
      }
    }

    return partialList;
  }
}
