package org.shipkit.internal.notes.util;

import java.io.*;
import java.net.URL;
import java.util.Scanner;

/**
 * IO utils. A bit of reinventing the wheel but we don't want extra dependencies at this stage and we want to be java.
 */
public class IOUtil {

    /**
     * Reads string from the file
     */
    public static String readFully(File input) {
        try {
            return readNow(new FileInputStream(input));
        } catch (Exception e) {
            throw new RuntimeException("Problems reading file: " + input, e);
        }
    }

    /**
     * Reads string from the file or returns empty text if file doesn't exist or can't open
     */
    public static String readFullyOrDefault(File input, String defaultValue) {
        try {
            return readNow(new FileInputStream(input));
        } catch (Exception e) {
            //TODO this potentially swallows exceptions
            //if the file does not exist, we should just use default value
            //if the file cannot be read, we should write a message to the log that we cannot use the file
            // + stack trace in debug level
            return defaultValue;
        }
    }

    /**
     * Reads string from the stream and closes it
     */
    public static String readFully(InputStream stream) {
        try {
            return readNow(stream);
        } catch (Exception e) {
            throw new RuntimeException("Problems reading stream", e);
        }
    }

    /**
     * Closes the target. Does nothing when target is null. Is not silent, throws exception on IOException.
     *
     * @param closeable the target, may be null
     */
    public static void close(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException e) {
                throw new RuntimeException("Problems closing closeable", e);
            }
        }
    }

    public static void createParentDirectory(File file) {
        createDirectory(file.getParentFile());
    }

    public static void createDirectory(File file) {
        if (!file.exists()) {
            createDirectory(file.getParentFile());
            file.mkdir();
        }
    }

    /**
     * Downloads resource and saves it to a given file
     * @param url location of resource to download
     * @param file destination file (not a directory!) where downloaded content will be stored
     *             (file or its parent directories don't need to exist)
     */
    public static void downloadToFile(String url, File file) {
        InputStream input = null;
        try {
            input = new BufferedInputStream(new URL(url).openStream());

            IOUtil.createParentDirectory(file);

            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(file);
                byte[] buf = new byte[1024];
                int n;
                while ((n = input.read(buf)) != -1) {
                    fos.write(buf, 0, n);
                }
            } finally {
                close(fos);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            close(input);
        }
    }

    private static String readNow(InputStream is) {
        Scanner s = new Scanner(is, "UTF-8").useDelimiter("\\A");
        try {
            return s.hasNext() ? s.next() : "";
        } finally {
            s.close();
        }
    }

    public static void writeFile(File target, String content) {
        PrintWriter p = null;
        try {
            target.getParentFile().mkdirs();
            p = new PrintWriter(new OutputStreamWriter(new FileOutputStream(target), "UTF-8"));
            p.write(content);
        } catch (Exception e) {
            throw new RuntimeException("Problems writing text to file: " + target, e);
        } finally {
            close(p);
        }
    }
}

@@ -1687,24 +1687,134 @@
 loseable) %7B%0A
+        close(closeable, false);%0A    %7D%0A%0A    private static void close(Closeable closeable, boolean quietly) %7B%0A
         if (
@@ -1917,32 +1917,68 @@
 OException e) %7B%0A
+                if (!quietly) %7B%0A    
                 
@@ -2050,27 +2050,285 @@
         
-%7D%0A        %7D
+    %7D%0A            %7D%0A        %7D%0A    %7D%0A%0A    /**%0A     * Closes the target. Does nothing when target is null. Is silent.%0A     *%0A     * @param closeable the target, may be null%0A     */%0A    public static void closeQuietly(Closeable closeable) %7B%0A        close(closeable, true);
 %0A    %7D%0A%0A
@@ -3473,16 +3473,23 @@
    close
+Quietly
 (fos);%0A 
@@ -3615,16 +3615,23 @@
    close
+Quietly
 (input);

introduce closeQuietly and make use of it