/**
 * Copyright (c) 2018-2024 Linagora
 * 
 * This program/library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or (at your
 * option) any later version.
 * 
 * This program/library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program/library; If not, see http://www.gnu.org/licenses/
 * for the GNU Lesser General Public License version 2.1.
 */
package org.ow2.petals.bc.filetransfer;

import java.io.File;
import java.net.URL;
import java.util.logging.LogRecord;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import org.junit.Before;
import org.junit.rules.TemporaryFolder;
import org.ow2.petals.commons.log.FlowLogData;
import org.ow2.petals.commons.log.PetalsExecutionContext;
import org.ow2.petals.component.framework.junit.Assert;
import org.ow2.petals.components.filetransfer.version_5.ObjectFactory;
import org.ow2.petals.junit.rules.log.handler.InMemoryLogHandler;

import com.ebmwebsourcing.easycommons.lang.UncheckedException;

/**
 * Abstract class for unit tests about request processing
 * 
 * @author Christophe DENEUX - Linagora
 * 
 */
public abstract class AbstractTest extends Assert {

    protected static final String SU_CONSUMER_NAME = "ft-consumes";

    protected static final String SU_PROVIDER_NAME = "ft-provides";

    protected static final InMemoryLogHandler IN_MEMORY_LOG_HANDLER = new InMemoryLogHandler();

    protected static final TemporaryFolder TEMP_FOLDER = new TemporaryFolder();

    protected static Marshaller MARSHALLER;

    protected static Unmarshaller UNMARSHALLER;

    static {
        final URL logConfig = AbstractTest.class.getResource("/logging.properties");
        assertNotNull("Logging configuration file not found", logConfig);
    }

    /**
     * All log traces must be cleared before starting a unit test (because the log handler is static and lives during
     * the whole suite of tests)
     */
    @Before
    public void clearLogTraces() {
        IN_MEMORY_LOG_HANDLER.clear();
    }

    @Before
    public void clearPetalsExecutionContext() {
        // JUnit is susceptible to reuse threads apparently
        PetalsExecutionContext.clear();
    }

    static {
        try {
            final JAXBContext context = JAXBContext.newInstance(ObjectFactory.class);
            UNMARSHALLER = context.createUnmarshaller();
            MARSHALLER = context.createMarshaller();
            MARSHALLER.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        } catch (final JAXBException e) {
            throw new UncheckedException(e);
        }
    }

    /**
     * <p>
     * Asserts that a log record is a MONIT trace associated to the start of an external service provider of the BC SQL.
     * If it isn't it throws an {@link AssertionError}.
     * </p>
     * <p>
     * In addition to the checks of {@link Assert#assertMonitProviderExtBeginLog(FlowLogData, LogRecord)}, the following
     * checks are applied:
     * </p>
     * <ul>
     * <li>the directory in which the FileTransfer operation takes place is the expected one,</li>
     * <li>the files managed by the FileTransfer operation takes place are the expected ones.</li>
     * </ul>
     * 
     * @param previousFlowLogData
     *            The flow attributes of the MONIT trace associated to the previous step
     * @param expectedDirectory
     *            The expected directory in which the FileTransfer operation takes place
     * @param expectedFilenames
     *            The filenames managed by the FileTransfer operation. Expected exact value for the field log data
     *            {@value FiletransferProvideExtFlowStepBeginLogData#FILE_NAMES_KEY}.
     * @param logRecord
     *            The actual log record to check
     * @return The flow log data of the log record
     */
    protected static FlowLogData assertMonitFileTransferProviderExtBeginLog(final FlowLogData previousFlowLogData,
            final File expectedDirectory, final String expectedFilenames, final LogRecord logRecord) {

        final FlowLogData flowLogData = Assert.assertMonitProviderExtBeginLog(previousFlowLogData, logRecord);

        if (expectedDirectory == null) {
            assertNull(flowLogData.get(FiletransferProvideExtFlowStepBeginLogData.DEST_DIR_NAME_KEY));
        } else {
            assertEquals(expectedDirectory.getAbsolutePath(),
                    flowLogData.get(FiletransferProvideExtFlowStepBeginLogData.DEST_DIR_NAME_KEY));
        }
        assertEquals(expectedFilenames, flowLogData.get(FiletransferProvideExtFlowStepBeginLogData.FILE_NAMES_KEY));

        return flowLogData;
    }

    /**
     * <p>
     * Asserts that a log record is a MONIT trace associated to the start of an external service provider of the BC SQL.
     * If it isn't it throws an {@link AssertionError}.
     * </p>
     * <p>
     * In addition to the checks of {@link Assert#assertMonitProviderExtBeginLog(FlowLogData, LogRecord)}, the following
     * checks are applied:
     * </p>
     * <ul>
     * <li>the directory in which the FileTransfer operation takes place is the expected one,</li>
     * <li>the files maanged by the FileTransfer operation takes place are the expected ones.</li>
     * </ul>
     * 
     * @param previousFlowLogData
     *            The flow attributes of the MONIT trace associated to the previous step
     * @param expectedDirectory
     *            The expected directory in which the FileTransfer operation takes place
     * @param expectedFilenames
     *            The filenames managed by the FileTransfer operation. The value of the field log data
     *            {@value FiletransferProvideExtFlowStepBeginLogData#FILE_NAMES_KEY} must contains each item of this
     *            array.
     * @param logRecord
     *            The actual log record to check
     * @return The flow log data of the log record
     */
    protected static FlowLogData assertMonitFileTransferProviderExtBeginLog(final FlowLogData previousFlowLogData,
            final File expectedDirectory, final String[] expectedFilenames, final LogRecord logRecord) {

        final FlowLogData flowLogData = Assert.assertMonitProviderExtBeginLog(previousFlowLogData, logRecord);

        assertEquals(expectedDirectory.getAbsolutePath(),
                flowLogData.get(FiletransferProvideExtFlowStepBeginLogData.DEST_DIR_NAME_KEY));
        for (final String expectedFilename : expectedFilenames) {
            assertTrue(((String) flowLogData.get(FiletransferProvideExtFlowStepBeginLogData.FILE_NAMES_KEY))
                    .contains(expectedFilename));
        }

        return flowLogData;
    }
}
