package org.checkerframework.framework.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;

public class ExecUtil {

  public static int execute(final String[] cmd, final OutputStream std, final OutputStream err) {

    final Redirection outRedirect = new Redirection(std, BLOCK_SIZE);
    final Redirection errRedirect = new Redirection(err, BLOCK_SIZE);

    try {
      final Process proc = Runtime.getRuntime().exec(cmd);
      outRedirect.redirect(proc.getInputStream());
      errRedirect.redirect(proc.getErrorStream());

      final IOException stdExc = outRedirect.join();
      final IOException errExc = errRedirect.join();
      final int exitStatus = proc.waitFor();

      if (stdExc != null) {
        throw stdExc;
      }

      if (errExc != null) {
        throw errExc;
      }

      return exitStatus;

    } catch (InterruptedException e) {
      throw new RuntimeException("Exception executing command: " + String.join(" ", cmd), e);
    } catch (IOException e) {
      throw new RuntimeException("Exception executing command: " + String.join(" ", cmd), e);
    }
  }

  public static final int BLOCK_SIZE = 1024;

  public static class Redirection {
    private final char[] buffer;
    private final OutputStreamWriter out;

    private Thread thread;
    private IOException exception;

    public Redirection(final OutputStream out, final int bufferSize) {
      this.buffer = new char[bufferSize];
      this.out = new OutputStreamWriter(out);
    }

    public void redirect(final InputStream inStream) {

      exception = null;

      this.thread =
          new Thread(
              () -> {
                final InputStreamReader in = new InputStreamReader(inStream);
                try {

                  int read = 0;
                  while (read > -1) {
                    read = in.read(buffer);
                    if (read > 0) {
                      out.write(buffer, 0, read);
                    }
                    out.flush();
                  }

                } catch (IOException exc) {
                  exception = exc;
                } finally {
                  quietlyClose(in);
                }
              });
      thread.start();
    }

    public IOException join() throws InterruptedException {
      thread.join();
      return exception;
    }
  }

  /**
   * Close the given writer, ignoring exceptions.
   *
   * @param writer the writer to close
   */
  @SuppressWarnings("EmptyCatch") // the purpose of this method is to ignore exceptions
  public static void quietlyClose(final Writer writer) {
    try {
      writer.close();
    } catch (IOException ioExc) {
    }
  }

  /**
   * Close the given reader, ignoring exceptions.
   *
   * @param reader the reader to close
   */
  @SuppressWarnings("EmptyCatch") // the purpose of this method is to ignore exceptions
  public static void quietlyClose(final Reader reader) {
    try {
      reader.close();
    } catch (IOException ioExc) {
    }
  }
}
