// Path: src/test/java/com/neo4j/docker/neo4jserver/plugins/ExampleNeo4jPlugin.java
// public class ExampleNeo4jPlugin
// {
//     // Output data class containing primitive types
//     public static class PrimitiveOutput
//     {
//         public String string;
//         public long integer;
//         public double aFloat;
//         public boolean aBoolean;
// 
//         public PrimitiveOutput( String string, long integer, double aFloat, boolean aBoolean )
//         {
//             this.string = string;
//             this.integer = integer;
//             this.aFloat = aFloat;
//             this.aBoolean = aBoolean;
//         }
//     }
// //    @ServiceProvider
// //    public static class ExampleConfigurationSetting implements SettingsDeclaration
// //    {
// //        public static final String CONF_NAME = "com.neo4j.docker.neo4jserver.plugins.loaded_verison";
// //
// //        @Description("Unique setting to identify which semver field was matched")
// //        public static final Setting<String> loadedVersionValue = SettingImpl.newBuilder(
// //                CONF_NAME,
// //                SettingValueParsers.STRING,
// //                "unset"
// //        ).build();
// //    }
// 
//     @Context
//     public GraphDatabaseService db;
// 
//     @Context
//     public Log log;
// 
//     // A Neo4j procedure that always returns fixed values
//     @Procedure
//     public Stream<PrimitiveOutput> defaultValues( @Name( value = "string", defaultValue = "a string" ) String string,
//                                                   @Name( value = "integer", defaultValue = "42" ) long integer,
//                                                   @Name( value = "float", defaultValue = "3.14" ) double aFloat,
//                                                   @Name( value = "boolean", defaultValue = "true" ) boolean aBoolean )
//     {
//         return Stream.of( new PrimitiveOutput( string, integer, aFloat, aBoolean ) );
//     }
// }
// 
// Path: src/test/java/com/neo4j/docker/neo4jserver/plugins/JarBuilder.java
// public class JarBuilder
// {
//     public URL createJarFor( File f, Class<?>... classesToInclude ) throws IOException
//     {
//         try ( FileOutputStream fout = new FileOutputStream( f ); JarOutputStream jarOut = new JarOutputStream( fout ) )
//         {
//             for ( Class<?> target : classesToInclude )
//             {
//                 String fileName = target.getName().replace( ".", "/" ) + ".class";
//                 jarOut.putNextEntry( new ZipEntry( fileName ) );
//                 jarOut.write( classCompiledBytes( fileName ) );
//                 jarOut.closeEntry();
//             }
//         }
//         return f.toURI().toURL();
//     }
// 
//     private byte[] classCompiledBytes( String fileName ) throws IOException
//     {
//         try ( InputStream in = getClass().getClassLoader().getResourceAsStream( fileName ) )
//         {
//             ByteArrayOutputStream out = new ByteArrayOutputStream();
//             while ( in.available() > 0 )
//             {
//                 out.write( in.read() );
//             }
// 
//             return out.toByteArray();
//         }
//     }
// }
// 
// Path: src/test/java/com/neo4j/docker/utils/TestSettings.java
// public static final Neo4jVersion NEO4J_VERSION = Neo4jVersion.fromVersionString( getVersionFromPropertyOrEnv() );


import com.github.dockerjava.api.command.CreateContainerCmd;
import com.google.gson.Gson;
import com.neo4j.docker.neo4jserver.plugins.ExampleNeo4jPlugin;
import com.neo4j.docker.utils.*;
import com.neo4j.docker.neo4jserver.plugins.JarBuilder;
import org.junit.Rule;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;
import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.Testcontainers;
import org.testcontainers.containers.Container;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.shaded.com.google.common.io.Files;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.neo4j.driver.Record;
import static com.neo4j.docker.utils.TestSettings.NEO4J_VERSION;

        container.withEnv( "NEO4J_AUTH", DB_USER+"/"+ DB_PASSWORD)
                .withEnv( "NEO4J_ACCEPT_LICENSE_AGREEMENT", "yes" )
                .withEnv( "NEO4JLABS_PLUGINS", "[\"_testing\"]" )
                .withExposedPorts( 7474, 7687 )
                .withLogConsumer( new Slf4jLogConsumer( log ) )
                .waitingFor( Wait.forHttp( "/" )
                                 .forPort( 7474 )
                                 .forStatusCode( 200 ) );

        SetContainerUser.nonRootUser( container );
        return container;
    }

    private File createTestVersionsJson(Path destinationFolder, String... versions) throws Exception
    {
        List<VersionsJsonEntry> entryList = Arrays.stream( versions )
                                                  .map( VersionsJsonEntry::new )
                                                  .collect( Collectors.toList() );
        Gson jsonBuilder = new Gson();
        String jsonStr = jsonBuilder.toJson( entryList );

        File outputJsonFile = destinationFolder.resolve( "versions.json" ).toFile();
        Files.write( jsonStr, outputJsonFile, StandardCharsets.UTF_8 );
        return outputJsonFile;
    }

    private void setupTestPlugin( Path pluginsDir, File versionsJson ) throws Exception
    {
       File myPluginJar = pluginsDir.resolve( PLUGIN_JAR ).toFile();
// Path: src/test/java/com/neo4j/docker/neo4jserver/plugins/ExampleNeo4jPlugin.java
// public class ExampleNeo4jPlugin
// {
//     // Output data class containing primitive types
//     public static class PrimitiveOutput
//     {
//         public String string;
//         public long integer;
//         public double aFloat;
//         public boolean aBoolean;
// 
//         public PrimitiveOutput( String string, long integer, double aFloat, boolean aBoolean )
//         {
//             this.string = string;
//             this.integer = integer;
//             this.aFloat = aFloat;
//             this.aBoolean = aBoolean;
//         }
//     }
// //    @ServiceProvider
// //    public static class ExampleConfigurationSetting implements SettingsDeclaration
// //    {
// //        public static final String CONF_NAME = "com.neo4j.docker.neo4jserver.plugins.loaded_verison";
// //
// //        @Description("Unique setting to identify which semver field was matched")
// //        public static final Setting<String> loadedVersionValue = SettingImpl.newBuilder(
// //                CONF_NAME,
// //                SettingValueParsers.STRING,
// //                "unset"
// //        ).build();
// //    }
// 
//     @Context
//     public GraphDatabaseService db;
// 
//     @Context
//     public Log log;
// 
//     // A Neo4j procedure that always returns fixed values
//     @Procedure
//     public Stream<PrimitiveOutput> defaultValues( @Name( value = "string", defaultValue = "a string" ) String string,
//                                                   @Name( value = "integer", defaultValue = "42" ) long integer,
//                                                   @Name( value = "float", defaultValue = "3.14" ) double aFloat,
//                                                   @Name( value = "boolean", defaultValue = "true" ) boolean aBoolean )
//     {
//         return Stream.of( new PrimitiveOutput( string, integer, aFloat, aBoolean ) );
//     }
// }
// 
// Path: src/test/java/com/neo4j/docker/neo4jserver/plugins/JarBuilder.java
// public class JarBuilder
// {
//     public URL createJarFor( File f, Class<?>... classesToInclude ) throws IOException
//     {
//         try ( FileOutputStream fout = new FileOutputStream( f ); JarOutputStream jarOut = new JarOutputStream( fout ) )
//         {
//             for ( Class<?> target : classesToInclude )
//             {
//                 String fileName = target.getName().replace( ".", "/" ) + ".class";
//                 jarOut.putNextEntry( new ZipEntry( fileName ) );
//                 jarOut.write( classCompiledBytes( fileName ) );
//                 jarOut.closeEntry();
//             }
//         }
//         return f.toURI().toURL();
//     }
// 
//     private byte[] classCompiledBytes( String fileName ) throws IOException
//     {
//         try ( InputStream in = getClass().getClassLoader().getResourceAsStream( fileName ) )
//         {
//             ByteArrayOutputStream out = new ByteArrayOutputStream();
//             while ( in.available() > 0 )
//             {
//                 out.write( in.read() );
//             }
// 
//             return out.toByteArray();
//         }
//     }
// }
// 
// Path: src/test/java/com/neo4j/docker/utils/TestSettings.java
// public static final Neo4jVersion NEO4J_VERSION = Neo4jVersion.fromVersionString( getVersionFromPropertyOrEnv() );


// Path: src/test/java/com/neo4j/docker/neo4jserver/TestPluginInstallation.java
import com.github.dockerjava.api.command.CreateContainerCmd;
import com.google.gson.Gson;
import com.neo4j.docker.neo4jserver.plugins.ExampleNeo4jPlugin;
import com.neo4j.docker.utils.*;
import com.neo4j.docker.neo4jserver.plugins.JarBuilder;
import org.junit.Rule;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;
import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.Testcontainers;
import org.testcontainers.containers.Container;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.shaded.com.google.common.io.Files;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.neo4j.driver.Record;
import static com.neo4j.docker.utils.TestSettings.NEO4J_VERSION;


        container.withEnv( "NEO4J_AUTH", DB_USER+"/"+ DB_PASSWORD)
                .withEnv( "NEO4J_ACCEPT_LICENSE_AGREEMENT", "yes" )
                .withEnv( "NEO4JLABS_PLUGINS", "[\"_testing\"]" )
                .withExposedPorts( 7474, 7687 )
                .withLogConsumer( new Slf4jLogConsumer( log ) )
                .waitingFor( Wait.forHttp( "/" )
                                 .forPort( 7474 )
                                 .forStatusCode( 200 ) );

        SetContainerUser.nonRootUser( container );
        return container;
    }

    private File createTestVersionsJson(Path destinationFolder, String... versions) throws Exception
    {
        List<VersionsJsonEntry> entryList = Arrays.stream( versions )
                                                  .map( VersionsJsonEntry::new )
                                                  .collect( Collectors.toList() );
        Gson jsonBuilder = new Gson();
        String jsonStr = jsonBuilder.toJson( entryList );

        File outputJsonFile = destinationFolder.resolve( "versions.json" ).toFile();
        Files.write( jsonStr, outputJsonFile, StandardCharsets.UTF_8 );
        return outputJsonFile;
    }

    private void setupTestPlugin( Path pluginsDir, File versionsJson ) throws Exception
    {
       File myPluginJar = pluginsDir.resolve( PLUGIN_JAR ).toFile();
        new JarBuilder().createJarFor( myPluginJar, ExampleNeo4jPlugin.class, ExampleNeo4jPlugin.PrimitiveOutput.class );