/*
 * 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 org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggingEvent;

import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import junit.framework.TestCase;

public class LoggingEventProcessorListTest extends TestCase {

  public void testMultipleProcessors() throws EventProcessorException {
    LinkedList<LoggingEventProcessor> list = new LinkedList<>();
    list.add(new MockEventProcessor(0));
    list.add(new MockEventProcessor(1));
    list.add(new MockEventProcessor(2));

    LoggingEventProcessorList loggingEventProcessorList = new LoggingEventProcessorList(list);
    assertEquals(loggingEventProcessorList.startProcessor(null).size(), 0);

    LoggingEvent loggingEvent = new LoggingEvent(this.getClass().getCanonicalName(),
        Logger.getRootLogger(), Level.INFO, "", null);
    List<SecureLoggingEvent> resultList = loggingEventProcessorList
        .processEvent(SecureLoggingEvent.newClientInstance(loggingEvent), null);

    assertEquals(resultList.size(), 8);
    for (SecureLoggingEvent secureLoggingEvent : resultList) {
      Map<String, String> properties = secureLoggingEvent.getSecureMessage().properties();
      for (int i = 0; i < list.size(); i++) {
        assertTrue(properties.containsKey(String.valueOf(i)));
      }
    }
  }

  public void testOneProcessor() throws EventProcessorException {
    LinkedList<LoggingEventProcessor> list = new LinkedList<>();
    list.add(new MockEventProcessor(0));

    LoggingEventProcessorList loggingEventProcessorList = new LoggingEventProcessorList(list);
    assertEquals(loggingEventProcessorList.startProcessor(null).size(), 0);

    LoggingEvent loggingEvent = new LoggingEvent(this.getClass().getCanonicalName(),
        Logger.getRootLogger(), Level.INFO, "", null);
    List<SecureLoggingEvent> resultList = loggingEventProcessorList
        .processEvent(SecureLoggingEvent.newClientInstance(loggingEvent), null);

    assertEquals(resultList.size(), 2);
    Map<String, String> properties = resultList.get(0).getSecureMessage().properties();
    assertTrue(properties.containsKey(String.valueOf(0)));
  }

  public void testZeroProcessors() throws EventProcessorException {
    LoggingEventProcessorList loggingEventProcessorList =
        new LoggingEventProcessorList(new LinkedList<LoggingEventProcessor>());
    assertEquals(loggingEventProcessorList.startProcessor(null).size(), 0);
    assertEquals(loggingEventProcessorList.stopProcessor(null).size(), 0);
  }

  private class MockEventProcessor implements LoggingEventProcessor {

    private final int _mockPropertyIndex;

    public MockEventProcessor(final int mockPropertyIndex) {
      super();
      _mockPropertyIndex = mockPropertyIndex;
    }

    @Override
    public void killProcessor() throws EventProcessorException {}

    @Override
    public List<SecureLoggingEvent> processEvent(final SecureLoggingEvent loggingEvent,
        final SecurePatternLayout layout) throws EventProcessorException {

      List<SecureLoggingEvent> result = new LinkedList<>();

      Map<String, String> properties = loggingEvent.getSecureMessage().properties();
      for (int i = 0; i < _mockPropertyIndex; i++) {
        properties.containsKey(String.valueOf(i));
      }
      properties = new LinkedHashMap<>(properties);
      properties.put(String.valueOf(_mockPropertyIndex), null);
      result.add(loggingEvent.addProperties(properties));
      result.add(loggingEvent.addProperties(properties));

      return result;
    }

    @Override
    public List<SecureLoggingEvent> startProcessor(final SecurePatternLayout layout)
        throws EventProcessorException {
      return new LinkedList<>();
    }

    @Override
    public List<SecureLoggingEvent> stopProcessor(final SecurePatternLayout layout)
        throws EventProcessorException {
      return new LinkedList<>();
    }

  }

}
