package ciir.jfoley.chai.io;

import ciir.jfoley.chai.Encodings;
import ciir.jfoley.chai.errors.FatalError;
import ciir.jfoley.chai.lang.Module;

import javax.xml.stream.XMLStreamWriter;
import java.io.*;

/**
 * @author jfoley.
 */
public class IO extends Module {

	/** Used for transfer operations */
	public static int BUFFER_SIZE = 8192;

	/** This class exists only to provide static methods. */
	private IO() {}

	/**
	 * Close anything!
	 * TODO: close with reflection if available?
	 */
	public static void close(Object obj) {
		try {
			if (obj != null) {
				if (obj instanceof Closeable) {
					((Closeable) obj).close();
				} else if (obj instanceof AutoCloseable) {
					((AutoCloseable) obj).close();
				} else if(obj instanceof XMLStreamWriter) {
					((XMLStreamWriter) obj).close();
				}
			}
		} catch (Exception ex) {
			throw new FatalError(ex);
		}
	}

	/** Read all data or "slurp" a BufferedReader. */
	public static String readAll(Reader reader, int bufferSize) throws IOException {
		final StringBuilder contents = new StringBuilder();
		char buf[] = new char[bufferSize];
		while(true) {
			int amt = reader.read(buf);
			if(amt < 0) break;
			contents.append(buf, 0, amt);
			if(amt < buf.length) break;
		}
		return contents.toString();
	}

	public static String readAll(Reader reader) throws IOException {
		return readAll(reader, BUFFER_SIZE);
	}

	/** Slurp a file, inspired by Clojure's naming. */
	public static String slurp(File path) throws IOException {
		try(Reader reader = openReader(path.getAbsolutePath())) {
			return readAll(reader);
		}
	}

	/** Spit a string to a file, inspired by Clojure's naming. */
	public static void spit(String data, File output) throws IOException {
		try (PrintWriter pw = openPrintWriter(output.getAbsolutePath())) {
			pw.print(data);
		}
	}

	public static Reader openReader(String file) throws IOException {
		return new InputStreamReader(openInputStream(file), Encodings.UTF8);
	}

	public static InputStream openInputStream(String file) throws IOException {
		return CompressionCodec.openInputStream(file);
	}
	public static OutputStream openOutputStream(String file) throws IOException {
		return CompressionCodec.openOutputStream(file);
	}

	public static PrintWriter openPrintWriter(String file) throws IOException {
		return new PrintWriter(openOutputStream(file));
	}

}

@@ -1828,16 +1828,24 @@
  static 
+Buffered
 Reader o
@@ -1901,16 +1901,35 @@
 urn new 
+BufferedReader(new 
 InputStr
@@ -1976,16 +1976,17 @@
 gs.UTF8)
+)
 ;%0A%09%7D%0A%0A%09p
@@ -2376,10 +2376,236 @@
 ));%0A%09%7D%0A%0A
+%09public static BufferedReader openReader(File fp) throws IOException %7B%0A%09%09return openReader(fp.getAbsolutePath());%0A%09%7D%0A%0A%09public static BufferedReader stringReader(String s) %7B%0A%09%09return new BufferedReader(new StringReader(s));%0A%09%7D%0A
 %7D%0A

Add a few more "reader" factory functions