package it.com.atlassian.bitbucket.mesh;

import com.atlassian.bitbucket.mesh.test.cluster.MeshClusterManager;
import com.atlassian.bitbucket.mesh.test.cluster.MeshClusterTestExecutionListener;
import com.atlassian.bitbucket.mesh.test.cluster.MeshControlPlane;
import com.atlassian.bitbucket.mesh.test.cluster.StandaloneMeshControlPlane;
import com.atlassian.bitbucket.mesh.test.context.ChainTestExecutionListener;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.test.context.TestExecutionListener;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Configuration
@PropertySource("classpath:application-control-plane.properties")
public class MeshIntegrationTestWiring {

    @Bean
    public TestExecutionListener chainExecutionListener(MeshClusterManager clusterManager) {
        return new ChainTestExecutionListener(ImmutableList.of(
                new DependencyInjectionTestExecutionListener(),
                new MeshClusterTestExecutionListener(clusterManager)
        ));
    }

    @Bean(destroyMethod = "shutdown")
    public MeshClusterManager clusterManager(MeshControlPlane controlPlane,
                                             ExecutorService executorService) throws IOException {
        Path homesRoot = Files.createTempDirectory("mesh-cluster").toRealPath(); //Use the default JVM temp directory
        return new MeshClusterManager(controlPlane, executorService, homesRoot, null);
    }

    @Bean(destroyMethod = "destroy")
    StandaloneMeshControlPlane controlPlane(@Value("${mesh.control-plane.partition-count:64}") int partitions) {
        return new StandaloneMeshControlPlane(partitions);
    }

    @Bean(destroyMethod = "shutdown")
    ExecutorService executorService() {
        return Executors.newCachedThreadPool(new ThreadFactoryBuilder()
                .setNameFormat("mesh-cluster-%d")
                .setDaemon(true)
                .build());
    }
}
