/**
 * Copyright (c) 2016-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.binding.rest;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Random;

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

import org.apache.mina.util.AvailablePortFinder;
import org.junit.Before;
import org.junit.rules.TemporaryFolder;
import org.ow2.petals.binding.rest.RESTConstants.HTTPServer;
import org.ow2.petals.binding.rest.junit.RestServer;
import org.ow2.petals.component.framework.junit.Assert;
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 int EMBEDDED_HTTP_SERVER_HTTP_PORT = AvailablePortFinder
            .getNextAvailable(HTTPServer.DEFAULT_HTTP_SERVER_PORT);

    protected static final int MOCK_REST_SERVER_HTTP_PORT = AvailablePortFinder
            .getNextAvailable(RestServer.DEFAULT_HTTP_PORT);

    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;

    protected static final String TEXT_NS = "http://petals.ow2.org/bc/rest/unit-test/text";

    protected static final QName TEXT_ITF = new QName(TEXT_NS, "Text");

    protected static final QName TEXT_SVC = new QName(TEXT_NS, "TextService");

    protected static final String TEXT_EDP = "textEndpointName";

    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
     */
    @Before
    public void clearLogTraces() {
        IN_MEMORY_LOG_HANDLER.clear();
    }

    static {
        try {
            final JAXBContext context = JAXBContext.newInstance(
                    org.ow2.petals.bc.rest.unit_test.text.ObjectFactory.class,
                    org.ow2.petals.bc.rest.unit_test.ged.ObjectFactory.class,
                    org.ow2.petals.bc.rest.unit_test.ged_auth.ObjectFactory.class,
                    org.ow2.petals.binding.rest.junit.data.Metadatas.class,
                    org.city.administrative_procedures.school_cafeteria_registration._1.ObjectFactory.class,
                    org.ow2.petals.tests.unit.placeholders._1.ObjectFactory.class);
            UNMARSHALLER = context.createUnmarshaller();
            MARSHALLER = context.createMarshaller();
            MARSHALLER.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        } catch (final JAXBException e) {
            throw new UncheckedException(e);
        }
    }

    /**
     * Create and initialize a byte array containing random text.
     */
    protected byte[] createAndInitializeTextByteArray(final long nbOf1kBlock) throws IOException {

        final String startTag = "BEGIN OF CONTENT";
        final String endTag = "END OF CONTENT";

        final Random randomizer = new Random();
        try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) {

            baos.write(startTag.getBytes());
            baos.write('\n');
            for (int i = 0; i < nbOf1kBlock; i++) {
                final String generatedContent = randomizer.ints(65, 90 + 1).limit(1024)
                        .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();

                baos.write(generatedContent.getBytes());
                baos.write('\n');
            }
            baos.write(endTag.getBytes());
            baos.flush();

            final byte[] data = baos.toByteArray();
            System.out.println("Array size:" + data.length);
            return data;
        }
    }
}
