package io.tetrapod.core.utils;

import io.tetrapod.core.json.JSONArray;

import java.io.*;
import java.net.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.security.*;
import java.util.*;

import javax.net.ssl.*;

/**
 * A random collection of useful static utility methods
 */
public class Util {

   public static final SecureRandom random = new SecureRandom();

   /**
    * Sleeps the current thread for a number of milliseconds, ignores interrupts.
    */
   public static void sleep(int millis) {
      try {
         Thread.sleep(millis);
      } catch (InterruptedException e) {}
   }

   /**
    * Get the hostname for this system
    */
   public static String getHostName() {
      try {
         return InetAddress.getLocalHost().getHostName();
      } catch (UnknownHostException e) {}
      return null;
   }

   /**
    * Takes a keystore input stream and a keystore password and return an SSLContext for TLS
    */
   public static SSLContext createSSLContext(InputStream keystoreStream, char[] pwd) throws IOException {
      try {
         final KeyStore trustStore = KeyStore.getInstance("JKS");
         trustStore.load(keystoreStream, pwd);
         final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
         trustManagerFactory.init(trustStore);
         final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
         keyManagerFactory.init(trustStore, pwd);
         final SSLContext ctx = SSLContext.getInstance("TLS");
         ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
         return ctx;
      } catch (Exception e) {
         throw new IOException(e);
      }
   }

   public static int random(int range) {
      return random.nextInt(range);
   }

   public static String format(String fmt, Object... args) {
      return String.format(fmt.replaceAll("\\{\\}", "%s"), args);
   }

   public static long nanosToMillis(long nanos) {
      return nanos / 1000000L;
   }

   public static <T> T random(final Collection<T> items) {
      return random(new ArrayList<T>(items));
   }

   public static <T> T random(final List<T> items) {
      return items.get(random(items.size()));
   }

   @SafeVarargs
   public static <T> T randomChoice(final T... items) {
      return items[random(items.length)];
   }

   public static int[] toIntArray(Collection<Integer> list) {
      int[] res = new int[list.size()];
      int i = 0;
      for (Iterator<Integer> iterator = list.iterator(); iterator.hasNext();) {
         res[i++] = iterator.next();
      }
      return res;
   }

   public static long[] toLongArray(List<Long> list) {
      long[] res = new long[list.size()];
      int i = 0;
      for (Iterator<Long> iterator = list.iterator(); iterator.hasNext();) {
         res[i++] = iterator.next();
      }
      return res;
   }

   public static boolean[] toBooleanArray(List<Boolean> list) {
      boolean[] res = new boolean[list.size()];
      int i = 0;
      for (Iterator<Boolean> iterator = list.iterator(); iterator.hasNext();) {
         res[i++] = iterator.next();
      }
      return res;
   }

   public static byte[] readFile(File f) throws IOException {
      return Files.readAllBytes(f.toPath());
   }

   public static String readFileAsString(File f) throws IOException {
      return new String(readFile(f), Charset.forName("UTF-8"));
   }

   public static int getProperty(String key, int defaultValue) {
      final String val = System.getProperty(key);
      if (val == null) {
         return defaultValue;
      }
      return Integer.parseInt(val);
   }

   public static String getProperty(String key, String defaultValue) {
      return System.getProperty(key, defaultValue);
   }

   public static String getProperty(String key) {
      return System.getProperty(key);
   }

   public static int runProcess(Callback<String> callback, String... commands) {
      ProcessBuilder pb = new ProcessBuilder(commands);
      pb.redirectErrorStream(true);
      try {
         Process p = pb.start();
         String s;
         BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
         while ((s = stdout.readLine()) != null) {
            if (callback != null)
               callback.call(s);
         }
         int rc = p.waitFor();
         p.getInputStream().close();
         p.getOutputStream().close();
         p.getErrorStream().close();
         return rc;
      } catch (Exception ex) {
         return -1;
      }
   }

   public static boolean getProperty(String key, boolean defaultValue) {
      final String val = System.getProperty(key);
      if (val == null) {
         return defaultValue;
      }
      return Boolean.parseBoolean(val);
   }

   public static boolean isLocal() {
      return Util.getProperty("devMode", "local").equals("local");
   }

   public static boolean isProduction() {
      return Util.getProperty("devMode", "local").equals("prod");
   }

   public static String formatFileSize(long bytes) {
      if (bytes < 4096) {
         return bytes + " bytes";
      } else if (bytes < 1024 * 1024) {
         return (Math.round(10 * bytes / 1024) / 10) + " kb";
      } else {
         return (Math.round(10 * bytes / (1024 * 1024)) / 10) + " mb";
      }
   }

   public static String escapeHTML(String text) {
      if (text == null) {
         return "";
      }
      StringBuilder sb = new StringBuilder();
      char[] chars = text.toCharArray();
      int i = 0;
      int n = chars.length;
      while (i < n) {
         char c = chars[i];

         // escape html < and > and &
         if (c == '<') {
            sb.append("&lt;");
            i++;
            continue;
         }
         if (c == '>') {
            sb.append("&gt;");
            i++;
            continue;
         }
         if (c == '&') {
            sb.append("&amp;");
            i++;
            continue;
         }
         if (c == '"') {
            sb.append("&quot;");
            i++;
            continue;
         }
         if (c == '\'') {
            sb.append("&#x27;");
            i++;
            continue;
         }

         i++;
         sb.append(c);
      }
      return sb.toString();
   }

   public static List<String> jsonArrayToStringList(JSONArray array) {
      List<String> result = new ArrayList<>();
      for (int i = 0; i < array.length(); i++) {
         result.add(array.getString(i));
      }
      return result;
   }

   public static List<Integer> jsonArrayToIntegerList(JSONArray array) {
      List<Integer> result = new ArrayList<>();
      for (int i = 0; i < array.length(); i++) {
         result.add(array.getInt(i));
      }
      return result;
   }

   public static int indexOf(int[] array, int element) {
      for (int i = 0; i < array.length; i++) {
         if (array[i] == element)
            return i;
      }
      return -1;
   }

}

@@ -363,16 +363,20 @@
  random 
+    
 = new Se
@@ -390,16 +390,330 @@
 dom();%0A%0A
+   public static long               ONE_SECOND = 1000;%0A   public static long               ONE_MINUTE = ONE_SECOND * 60;%0A   public static long               ONE_HOUR   = ONE_MINUTE * 60;%0A   public static long               ONE_DAY    = ONE_HOUR * 24;%0A   public static long               ONE_WEEK   = ONE_DAY * 7;%0A%0A
    /**%0A 

Add sme useful constants for milliscond times