/*
 * 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.ea.services.infrastructure.persistence;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.Security;
import java.util.Arrays;

import org.apache.commons.io.FileUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;

import com.scytl.products.oscore.logging.api.domain.TransactionInfo;
import com.scytl.products.oscore.logging.api.formatter.MessageFormatter;
import com.scytl.products.oscore.logging.api.writer.SecureLoggingWriter;
import com.scytl.products.oscore.logging.core.factory.SecureLoggingFactoryLog4j;
import com.scytl.products.oscore.logging.core.formatter.SplunkFormatter;
import com.scytl.products.oscore.logging.core.provider.TransactionInfoProvider;

public class ExtendedAuthenticationTest {

    public static final String SECURE_LOGGER_FILE = "target/extended_authentication_test_secure.log";

    @BeforeClass
    public static void setup() {
        Security.addProvider(new BouncyCastleProvider());
    }

    @Before
    public void setupSecureLogger() {
        // clear content if it exists
        File secureLogFile = Paths.get(SECURE_LOGGER_FILE).toFile();
        if (secureLogFile.exists()) {
            try {
                FileUtils.write(secureLogFile, "");
            } catch (IOException e) {
                // ignore
            }
        }
    }

    protected void assertSecureLogContainsMessage(final String level, final String message, String... additionalInfoTokens)
            throws IOException {
        Path logFile = Paths.get(SECURE_LOGGER_FILE).toAbsolutePath();

        Assert.assertTrue(Files.lines(logFile).filter(line -> {
            final String[] tokens = line.split("\\|");
            if (tokens[1].equalsIgnoreCase(level)) {
                String additionalInfo = tokens[17];
                // log message contains all the mandatory tokens?
                boolean allIncluded = additionalInfoTokens.length <= 0
                    || Arrays.stream(additionalInfoTokens).allMatch(t -> additionalInfo.contains(t));
                return (tokens[16].equalsIgnoreCase(message) && allIncluded);
            } else
                return false;
        }).findFirst().isPresent());
    }

    public SecureLoggingWriter getSecureLoggingWriter() {
        TransactionInfo transactionInfo = mock(TransactionInfo.class);
        TransactionInfoProvider transactionInfoProvider = mock(TransactionInfoProvider.class);
        when(transactionInfo.getTrackId()).thenReturn(1L);
        when(transactionInfo.getServerIpAddress()).thenReturn("0.0.0.0");
        when(transactionInfo.getClientIpAddress()).thenReturn("0.0.0.0");
        when(transactionInfo.getTenant()).thenReturn("tenant");
        when(transactionInfoProvider.get()).thenReturn(transactionInfo);

        MessageFormatter messageFormatter = new SplunkFormatter("Test", "Test", transactionInfoProvider);
        SecureLoggingFactoryLog4j loggerFactory = new SecureLoggingFactoryLog4j(messageFormatter);
        SecureLoggingWriter secureLoggingWriter = loggerFactory.getLogger("test-secure-logger");

        return secureLoggingWriter;
    }

}
