package org.carlspring.strongbox.testing.artifact;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import javax.annotation.PreDestroy;

import org.carlspring.strongbox.artifact.generator.ArtifactGenerator;
import org.carlspring.strongbox.booters.PropertiesBooter;
import org.carlspring.strongbox.providers.io.RepositoryPath;
import org.carlspring.strongbox.providers.io.RepositoryPathResolver;
import org.carlspring.strongbox.services.ArtifactManagementService;
import org.junit.jupiter.api.TestInfo;
import org.springframework.cglib.proxy.UndeclaredThrowableException;

/**
 * @author sbespalov
 *
 */
public class TestArtifactContext implements AutoCloseable
{

    private final TestArtifact testArtifact;
    private final PropertiesBooter propertiesBooter;
    private final ArtifactManagementService artifactManagementService;
    private final RepositoryPathResolver repositoryPathResolver;
    private final TestInfo testInfo;
    private final Path artifactPath;

    public TestArtifactContext(TestArtifact testArtifact,
                               PropertiesBooter propertiesBooter,
                               ArtifactManagementService artifactManagementService,
                               RepositoryPathResolver repositoryPathResolver,
                               TestInfo testInfo)
        throws IOException
    {
        this.testArtifact = testArtifact;
        this.propertiesBooter = propertiesBooter;
        this.artifactManagementService = artifactManagementService;
        this.repositoryPathResolver = repositoryPathResolver;
        this.testInfo = testInfo;

        artifactPath = createArtifact();
    }

    private Path createArtifact()
        throws IOException
    {
        Class<? extends ArtifactGenerator> generatorClass = testArtifact.generator();

        Path vaultDirectoryPath = Paths.get(propertiesBooter.getVaultDirectory(), ".temp",
                                            testInfo.getTestClass().get().getSimpleName(),
                                            testInfo.getTestMethod().get().getName());

        ArtifactGenerator artifactGenerator;
        try
        {
            artifactGenerator = generatorClass.getConstructor(Path.class).newInstance(vaultDirectoryPath);
        }
        catch (Exception e)
        {
            throw new IOException(e);
        }

        Path artifactPathLocal = artifactGenerator.generateArtifact(URI.create(testArtifact.resource()),
                                                                    testArtifact.size());
        if (testArtifact.repository().isEmpty())
        {
            return artifactPathLocal;
        }

        RepositoryPath repositoryPath = repositoryPathResolver.resolve(testArtifact.storage(),
                                                                       testArtifact.repository(),
                                                                       testArtifact.resource());
        artifactManagementService.store(repositoryPath, Files.newInputStream(artifactPathLocal));
        repositoryPath.getFileSystem()
                      .provider()
                      .resolveChecksumPathMap(repositoryPath)
                      .values()
                      .stream()
                      .forEach(p -> {
                          try(InputStream is = Files.newInputStream(artifactPathLocal.resolveSibling(p.getFileName())))
                          {
                              artifactManagementService.store(p,is);
                          }
                          catch (IOException e)
                          {
                              throw new UndeclaredThrowableException(e);
                          }
                      });

        Files.delete(artifactPathLocal);
        return repositoryPath;
    }

    public Path getArtifact()
    {
        return artifactPath;
    }

    @PreDestroy
    @Override
    public void close()
        throws Exception
    {
        Files.deleteIfExists(artifactPath);
    }

    public static String id(TestArtifact testArtifact)
    {
        return String.format("%s", testArtifact.resource());
    }

}

@@ -3038,24 +3038,109 @@
 esource());%0A
+        try (InputStream is = Files.newInputStream(artifactPathLocal))%0A        %7B%0A    
         arti
@@ -3183,36 +3183,51 @@
 ryPath, 
-Files.newInputStream
+is);%0A        %7D%0A        Files.delete
 (artifac
@@ -3237,18 +3237,18 @@
 thLocal)
-)
 ;
+%0A
 %0A       
@@ -3507,50 +3507,28 @@
     
-try(InputStream is = Files.newInputStream(
+Path checksumPath = 
 arti
@@ -3572,16 +3572,99 @@
 eName())
+;%0A                          try (InputStream is = Files.newInputStream(checksumPath
 ))%0A     
@@ -3750,21 +3750,80 @@
 store(p,
+ 
 is);%0A
+                              Files.delete(checksumPath);%0A
         
@@ -4050,49 +4050,8 @@
 );%0A%0A
-        Files.delete(artifactPathLocal);%0A
     

fix Windows resource leaks