package de.gurkenlabs.util.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public final class FileUtilities {
  private static final Logger log = Logger.getLogger(FileUtilities.class.getName());
  private static final String[] DIR_BLACKLIST = new String[] { "\\bin", "\\screenshots" };

  private FileUtilities() {
  }

  public static boolean deleteDir(final File dir) {
    if (dir.isDirectory()) {
      final String[] children = dir.list();
      for (int i = 0; i < children.length; i++) {
        final boolean success = deleteDir(new File(dir, children[i]));
        if (!success) {
          return false;
        }
      }
    }

    try {
      Files.delete(dir.toPath().toAbsolutePath());
    } catch (IOException e) {
      log.log(Level.SEVERE, e.getMessage(), e);
      return false;
    }

    return true;
  }

  public static List<String> findFiles(final List<String> fileNames, final Path dir, final String extension) {
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
      for (final Path path : stream) {
        if (path.toFile().isDirectory()) {
          if (isBlackListedDirectory(path)) {
            continue;
          }

          findFiles(fileNames, path, extension);
        } else if (path.toAbsolutePath().toString().endsWith(extension)) {
          fileNames.add(path.toAbsolutePath().toString());
        }
      }
    } catch (final IOException e) {
      log.log(Level.SEVERE, e.getMessage(), e);
    }

    return fileNames;
  }

  public static List<String> findFiles(final List<String> fileNames, final Path dir, final String... files) {
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
      for (final Path path : stream) {
        if (path.toFile().isDirectory()) {
          if (isBlackListedDirectory(path)) {
            continue;
          }

          findFiles(fileNames, path, files);
        } else {
          for (final String file : files) {
            if (path.toAbsolutePath().toString().endsWith(file)) {

              fileNames.add(path.toAbsolutePath().toString());
            }
          }
        }
      }
    } catch (final IOException e) {
      log.log(Level.SEVERE, e.getMessage(), e);
    }

    return fileNames;
  }

  private static boolean isBlackListedDirectory(Path path) {
    for (final String black : DIR_BLACKLIST) {
      if (path.toAbsolutePath().toString().contains(black)) {
        return true;
      }
    }

    return false;
  }

  public static String getExtension(final File file) {
    return getExtension(file.getAbsolutePath());
  }

  public static String getExtension(final String fileName) {
    try {
      return fileName.substring(fileName.lastIndexOf('.') + 1);
    } catch (final Exception e) {
      return "";
    }
  }

  public static String getFileName(final String path) {
    if (path == null || path.isEmpty()) {
      return "";
    }

    String name = path;
    final int pos = name.lastIndexOf('.');
    if (pos > 0) {
      name = name.substring(0, pos);
    }

    final int lastBackslash = name.lastIndexOf('/');
    if (lastBackslash != -1) {
      name = name.substring(lastBackslash + 1, name.length());
    } else {
      final int lastForwardSlash = name.lastIndexOf('\\');
      if (lastForwardSlash != -1) {
        name = name.substring(lastForwardSlash + 1, name.length());
      }
    }

    return name;
  }

  /**
   * Gets the specified file from either a resource folder or the file system.
   * 
   * @param file
   * @return
   */
  public static InputStream getGameResource(final String file) {
    try {
      final InputStream resourceStream = ClassLoader.getSystemResourceAsStream(file);
      if (resourceStream != null) {
        return resourceStream;
      }

      final InputStream resourceStream2 = FileUtilities.class.getResourceAsStream(file);
      if (resourceStream2 != null) {
        return resourceStream2;
      }
      File f = new File(file);
      if (f.exists()) {
        return new FileInputStream(file);
      } else {
        log.log(Level.INFO, "{0} could not be found.", file);
        return null;
      }
    } catch (final IOException e) {
      log.log(Level.SEVERE, e.getMessage(), e);
      return null;
    }
  }

  public static String getParentDirPath(final String fileOrDirPath) {
    if (fileOrDirPath.contains(File.separator)) {
      return fileOrDirPath.substring(0, fileOrDirPath.lastIndexOf(File.separatorChar, fileOrDirPath.length()));
    } else if (fileOrDirPath.contains("/")) {
      return fileOrDirPath.substring(0, fileOrDirPath.lastIndexOf('/') + 1);
    }

    return "";
  }
}

@@ -27,16 +27,53 @@
 .io;%0D%0A%0D%0A
+import java.io.BufferedInputStream;%0D%0A
 import j
@@ -4003,38 +4003,32 @@
    try %7B%0D%0A      
-final 
 InputStream reso
@@ -4130,32 +4130,56 @@
 %0A        return 
+new BufferedInputStream(
 resourceStream;%0D
@@ -4176,16 +4176,17 @@
 ceStream
+)
 ;%0D%0A     
@@ -4201,26 +4201,8 @@
     
-final InputStream 
 reso
@@ -4211,17 +4211,16 @@
 ceStream
-2
  = FileU
@@ -4286,17 +4286,16 @@
 ceStream
-2
  != null
@@ -4314,16 +4314,40 @@
  return 
+new BufferedInputStream(
 resource
@@ -4356,9 +4356,9 @@
 ream
-2
+)
 ;%0D%0A 
@@ -4361,24 +4361,26 @@
 ;%0D%0A      %7D%0D%0A
+%0D%0A
       File f
@@ -4430,28 +4430,38 @@
 %0D%0A        re
-turn
+sourceStream =
  new FileInp
@@ -4473,24 +4473,81 @@
 eam(file);%0D%0A
+        return new BufferedInputStream(resourceStream);%0D%0A
       %7D else

Improve the FileUtilities implementation by providing a BufferedInputStream wrapper for game resources