package io.quarkus.runtime;

import java.io.Closeable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

import org.jboss.logging.Logger;

public class StartupContext implements Closeable {

    public static final String RAW_COMMAND_LINE_ARGS = StartupContext.class.getName() + ".raw-command-line-args";

    private static final Logger LOG = Logger.getLogger(StartupContext.class);

    private final Map<String, Object> values = new HashMap<>();
    private Object lastValue;
    // this is done to distinguish between the value never having been set and having been set as null
    private boolean lastValueSet = false;
    private final List<Runnable> shutdownTasks = new ArrayList<>();
    private final List<Runnable> lastShutdownTasks = new ArrayList<>();
    private final ShutdownContext shutdownContext = new ShutdownContext() {
        @Override
        public void addShutdownTask(Runnable runnable) {
            shutdownTasks.add(runnable);
        }

        @Override
        public void addLastShutdownTask(Runnable runnable) {
            lastShutdownTasks.add(runnable);
        }
    };
    private String[] commandLineArgs;
    private String currentBuildStepName;

    public StartupContext() {
        values.put(ShutdownContext.class.getName(), shutdownContext);
        values.put(RAW_COMMAND_LINE_ARGS, new Supplier<String[]>() {
            @Override
            public String[] get() {
                if (commandLineArgs == null) {
                    throw new RuntimeException("Command line arguments not available during static init");
                }
                return commandLineArgs;
            }
        });
    }

    public void putValue(String name, Object value) {
        values.put(name, value);
        lastValueSet = true;
        this.lastValue = value;
    }

    public Object getValue(String name) {
        return values.get(name);
    }

    public Object getLastValue() {
        return lastValue;
    }

    public boolean isLastValueSet() {
        return lastValueSet;
    }

    @Override
    public void close() {
        runAllInReverseOrder(shutdownTasks);
        shutdownTasks.clear();
        runAllInReverseOrder(lastShutdownTasks);
        lastShutdownTasks.clear();
    }

    private void runAllInReverseOrder(List<Runnable> tasks) {
        List<Runnable> toClose = new ArrayList<>(tasks);
        Collections.reverse(toClose);
        for (Runnable r : toClose) {
            try {
                r.run();
            } catch (Throwable e) {
                LOG.error("Running a shutdown task failed", e);
            }
        }
    }

    @SuppressWarnings("unused")
    public void setCommandLineArguments(String[] commandLineArguments) {
        this.commandLineArgs = commandLineArguments;
    }

    @SuppressWarnings("unused")
    public String getCurrentBuildStepName() {
        return currentBuildStepName;
    }

    @SuppressWarnings("unused")
    public void setCurrentBuildStepName(String currentBuildStepName) {
        this.currentBuildStepName = currentBuildStepName;
    }
}

@@ -645,20 +645,20 @@
 lue 
-never 
 having
+ never
  bee
@@ -733,16 +733,107 @@
  false;%0A
+    // the initial capacity was determined experimentally for a standard set of extensions%0A
     priv
@@ -881,32 +881,33 @@
 new ArrayList%3C%3E(
+9
 );%0A    private f
@@ -962,16 +962,17 @@
 yList%3C%3E(
+7
 );%0A    p
@@ -978,21 +978,121 @@
 private 
-final
+String%5B%5D commandLineArgs;%0A    private String currentBuildStepName;%0A%0A    public StartupContext() %7B%0A       
  Shutdow
@@ -1142,32 +1142,36 @@
 ext() %7B%0A        
+    
 @Override%0A      
@@ -1164,32 +1164,36 @@
 verride%0A        
+  
+  
 public void addS
@@ -1229,32 +1229,36 @@
 ) %7B%0A            
+    
 shutdownTasks.ad
@@ -1274,24 +1274,28 @@
 e);%0A        
+    
 %7D%0A%0A        @
@@ -1285,32 +1285,36 @@
      %7D%0A%0A        
+ 
+   
 @Override%0A      
@@ -1299,32 +1299,36 @@
       @Override%0A
+    
         public v
@@ -1376,32 +1376,36 @@
 ) %7B%0A            
+   
+ 
 lastShutdownTask
@@ -1433,126 +1433,24 @@
     
-%7D%0A
     %7D
-;
 %0A    
-private String%5B%5D commandLineArgs;%0A    private String currentBuildStepName;%0A%0A    public StartupContext() %7B
+    %7D;
 %0A   

Apply minor polish to StartupContext