package io.tweag.sparkle;

import java.io.*;
import java.net.*;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.zip.*;

public class Sparkle {
    static {
        System.out.println("Loading Sparkle application ...");
        try {
            InputStream in =
                Sparkle.class.getResourceAsStream("/sparkle-app.zip");
            File sparkleAppZipFile =
                File.createTempFile("sparkle-app-", ".zip");
            Files.copy(in, sparkleAppZipFile.toPath(),
                StandardCopyOption.REPLACE_EXISTING);
            in.close();
            loadApplication(sparkleAppZipFile, "hsapp");
            sparkleAppZipFile.delete();
        } catch (Exception e) {
            System.out.println(e);
            throw new ExceptionInInitializerError(e);
        }
        System.out.println("Application loaded.");
        Sparkle.initializeHaskellRTS();
    }

    public static void loadApplication(File archive, String appName)
        throws IOException
    {
        // Extract all files from the .zip archive.
        //
        ZipFile zip = new ZipFile(archive);
        String tmpDir = System.getProperty("java.io.tmpdir");
        Path sparkleAppTmpDir =
            Files.createTempDirectory(Paths.get(tmpDir), "sparkle-app-");
        ArrayList<Path> pathsList = new ArrayList();
        for (Enumeration e = zip.entries(); e.hasMoreElements(); ) {
            ZipEntry entry = (ZipEntry)e.nextElement();
            InputStream in = zip.getInputStream(entry);
            Path path = sparkleAppTmpDir.resolve(entry.getName());
            pathsList.add(path);
            Files.copy(in, path);
            in.close();
        }
        zip.close();

        // Dynamically load the app.
        //
        System.load(sparkleAppTmpDir.resolve(appName).toString());

        // Delete the app binary and its libraries, now that they are loaded.
        //
        for (Iterator<Path> i = pathsList.iterator(); i.hasNext(); ) {
            i.next().toFile().delete();
        }
        sparkleAppTmpDir.toFile().delete();
    }

    public static native void bootstrap();
    public static native <R> R apply(byte[] cos, Object... args);
    private static native void initializeHaskellRTS();
}

@@ -627,32 +627,52 @@
     in.close();%0A
+            try %7B%0A  
             load
@@ -708,24 +708,50 @@
 , %22hsapp%22);%0A
+            %7D finally %7B%0A  
             
@@ -770,32 +770,46 @@
 pFile.delete();%0A
+            %7D%0A
         %7D catch 
@@ -1447,24 +1447,40 @@
 rrayList();%0A
+        try %7B%0A  
         for 
@@ -1806,34 +1806,38 @@
 lose();%0A        
-%7D%0A
+  %7D%0A  
         zip.clos
@@ -1838,24 +1838,26 @@
 p.close();%0A%0A
+  
         // D
@@ -1881,35 +1881,39 @@
 he app.%0A        
+  
 //%0A
+  
         System.l
@@ -1963,17 +1963,38 @@
 ing());%0A
-%0A
+        %7D finally %7B%0A  
         
@@ -2063,35 +2063,39 @@
 loaded.%0A        
+  
 //%0A
+  
         for (Ite
@@ -2095,65 +2095,27 @@
 or (
-Iterator%3CPath%3E i = pathsList.iterator(); i.hasNext(); ) %7B
+Path p : pathsList)
 %0A   
@@ -2127,16 +2127,9 @@
     
-i.next()
+p
 .toF

Remove temporary files even on error.