/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.jdo.exectck;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.CharBuffer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import javax.jdo.JDOException;

public class Utilities {

  Utilities() {}

  private static final String DATE_FORMAT_NOW = "yyyyMMdd-HHmmss";

  /*
   * Return the current date/time as a String.
   */
  public static String now() {
    Calendar cal = Calendar.getInstance();
    SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
    return sdf.format(cal.getTime());
  }

  /*
   * From an array of URLs, create a classpath String suitable for use
   * as a command line argument
   */
  public static String urls2ClasspathString(List<URL> urls) {
    StringBuilder cp = new StringBuilder();

    for (URL url : urls) {
      cp.append(url.getPath());
      cp.append(File.pathSeparator);
    }
    return cp.toString();
  }

  public static String removeSubstrs(String original, String exclude) {
    String[] deleteThese = exclude.split(" ");
    String filtered = original;
    for (String sub : deleteThese) {
      filtered = filtered.replaceAll(sub.trim(), "");
    }
    return filtered.trim();
  }

  public static void printClasspath(ClassLoader loader) {
    if (loader instanceof URLClassLoader) {
      // Get the URLs
      URL[] urls = ((URLClassLoader) loader).getURLs();
      System.out.println(urls.length + " URL(s) for loader: ");
      for (URL url : urls) {
        if (url != null) {
          System.out.println("    " + url.getFile());
        }
      }
    }
  }

  public void printClasspath() {

    // Get the System Classloader
    printClasspath(ClassLoader.getSystemClassLoader());

    // Get the System Classloader
    printClasspath(Thread.currentThread().getContextClassLoader());
  }

  static String readFile(String fileName) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader(fileName));
    String line = null;
    StringBuffer stringBuf = new StringBuffer();
    String ls = System.getProperty("line.separator");
    while ((line = reader.readLine()) != null) {
      stringBuf.append(line);
      stringBuf.append(ls);
    }
    return stringBuf.toString();
  }

  InvocationResult invokeTest(List<String> command) {
    return invokeTest(new ProcessBuilder(command));
  }

  InvocationResult invokeTest(List<String> command, File directory) {
    ProcessBuilder builder = new ProcessBuilder(command);
    builder.directory(directory);
    return invokeTest(builder);
  }

  private InvocationResult invokeTest(ProcessBuilder builder) {
    InvocationResult result = new InvocationResult();
    try {
      Process proc = builder.start();
      InputStream stdout = proc.getInputStream();
      InputStream stderr = proc.getErrorStream();
      CharBuffer outBuffer = CharBuffer.allocate(1000000);
      CharBuffer errBuffer = CharBuffer.allocate(1000000);
      Thread outputThread = createReaderThread(stdout, outBuffer);
      Thread errorThread = createReaderThread(stderr, errBuffer);
      int exitValue = proc.waitFor();
      result.setExitValue(exitValue);
      errorThread.join(10000); // wait ten seconds to get stderr after process terminates
      outputThread.join(10000); // wait ten seconds to get stdout after process terminates
      result.setErrorString(errBuffer.toString());
      result.setOutputString(outBuffer.toString());
      // wait until the Enhancer command finishes
    } catch (InterruptedException ex) {
      throw new RuntimeException("InterruptedException", ex);
    } catch (IOException ex) {
      throw new RuntimeException("IOException", ex);
    } catch (JDOException jdoex) {
      jdoex.printStackTrace();
      Throwable[] throwables = jdoex.getNestedExceptions();
      System.out.println("Exception throwables of size: " + throwables.length);
      for (Throwable throwable : throwables) {
        throwable.printStackTrace();
      }
    }
    return result;
  }

  private Thread createReaderThread(final InputStream input, final CharBuffer output) {
    final Reader reader = new InputStreamReader(input);
    Thread thread =
        new Thread(
            new Runnable() {
              public void run() {
                int count = 0;
                int outputBytesRead = 0;
                try {
                  while (-1 != (outputBytesRead = reader.read(output))) {
                    count += outputBytesRead;
                  }
                } catch (IOException e) {
                  e.printStackTrace();
                } finally {
                  output.flip();
                }
              }
            });
    thread.start();
    return thread;
  }

  class InvocationResult {
    private int exitValue;
    private String errorString;
    private String outputString;

    int getExitValue() {
      return exitValue;
    }

    private void setExitValue(int exitValue) {
      this.exitValue = exitValue;
    }

    private void setErrorString(String errorString) {
      this.errorString = errorString;
    }

    String getErrorString() {
      return errorString;
    }

    private void setOutputString(String outputString) {
      this.outputString = outputString;
    }

    String getOutputString() {
      return outputString;
    }
  }
}
