/*
 * 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.ui.ws.rs.application;

import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.URL;
import java.security.Security;

import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.eu.ingwar.tools.arquillian.extension.suite.annotations.ArquillianSuiteDeployment;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.shrinkwrap.api.Filters;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;

import com.scytl.products.ov.commons.beans.domain.model.certificate.CertificateEntity;
import com.scytl.products.ov.commons.infrastructure.remote.service.RemoteCertificateServiceImpl;
import com.scytl.products.ov.commons.ui.ws.rs.ObjectMappers;
import com.scytl.products.ov.commons.ui.ws.rs.exceptions.ApplicationExceptionHandler;
import com.scytl.products.ov.commons.ui.ws.rs.exceptions.DuplicateEntryExceptionHandler;
import com.scytl.products.ov.commons.ui.ws.rs.exceptions.GlobalExceptionHandler;
import com.scytl.products.ov.commons.ui.ws.rs.exceptions.ResourceNotFoundExceptionHandler;
import com.scytl.products.ov.commons.ui.ws.rs.exceptions.RetrofitErrorHandler;
import com.scytl.products.ov.commons.ui.ws.rs.exceptions.ValidationExceptionHandler;
import com.scytl.products.ov.ea.services.infrastructure.health.HealthCheckRegistryProducer;
import com.scytl.products.ov.ea.services.infrastructure.remote.EaRemoteCertificateServiceImpl;
import com.scytl.products.ov.ea.ui.ws.rs.application.it.RemoteCertificateServiceForTests;
import com.scytl.products.ov.ea.ui.ws.rs.application.it.SystemPropertiesLoader;
import com.sun.net.httpserver.HttpServer;

@ArquillianSuiteDeployment
@SuppressWarnings("restriction")
public class ExtendedAuthenticationArquillianDeployment extends ExtendedAuthenticationBaseITestCase {

    private static final String ADMIN_BOARD_CERT_URL =
        "/CR/certificates/public/name/AdministrationBoard " + TEST_ADMINBOARD_ID;

    private static final SystemPropertiesLoader spl = new SystemPropertiesLoader();

    static HttpServer mockHTTPServer;

    static {
        spl.setProperties();
    }

    @Deployment
    public static WebArchive createDeployment() throws Exception {

        Security.addProvider(new BouncyCastleProvider());
        final String crContext = spl.load().getProperty(RemoteCertificateServiceImpl.CERTIFICATES_CONTEXT_URL_PROPERTY);
        final Integer serverPort = new URL(crContext).getPort();

        createCryptoMaterial();
        setupHttpServer(serverPort);

        return ShrinkWrap.create(WebArchive.class, "ea-ws-rest.war")
                .addClasses(org.slf4j.Logger.class)
                .addPackage("com.scytl.products.oscore")
                .addPackage("com.scytl.cryptolib")
                .addPackages(true, "org.h2")
                .addPackages(true, "com.fasterxml.jackson.jaxrs")
                .addPackages(true, "com.scytl.products.ov.ea.ui")
                .addPackages(true, "com.scytl.products.ov.ea.services")
                .addPackages(true, "com.scytl.products.ov.ea.domain")
                .addPackages(true,
                Filters.exclude(ResourceNotFoundExceptionHandler.class, GlobalExceptionHandler.class,
                    ValidationExceptionHandler.class, ApplicationExceptionHandler.class,
                    DuplicateEntryExceptionHandler.class, RetrofitErrorHandler.class, BouncyCastleProvider.class),
                "com.scytl.products.ov.commons")
                .deleteClass(EaRemoteCertificateServiceImpl.class).deleteClass(HealthCheckRegistryProducer.class)
                .addClass(RemoteCertificateServiceForTests.class).addAsResource("log4j.xml")
                .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
                .addAsManifestResource("test-persistence.xml", "persistence.xml");
    }

    private static void setupHttpServer(int port) {

        try {

            final InetSocketAddress address = new InetSocketAddress(port);
            mockHTTPServer = HttpServer.create(address, 0);
            mockHTTPServer.createContext(ADMIN_BOARD_CERT_URL, crHandler -> {

                CertificateEntity ce = new CertificateEntity();
                ce.setCertificateContent(certificateString);
                final String response = ObjectMappers.toJson(ce);
                crHandler.getResponseHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
                crHandler.sendResponseHeaders(Response.Status.OK.getStatusCode(), response.length());
                final OutputStream os = crHandler.getResponseBody();
                os.write(response.getBytes());
                os.close();

            });

            mockHTTPServer.setExecutor(null); // creates a default executor
            mockHTTPServer.start();

        } catch (Exception exception) {
            throw new RuntimeException("Failed to create HTTP server on free port of localhost", exception);
        }
    }
}
