package ru.r2cloud.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class Util {

	private static final Logger LOG = LoggerFactory.getLogger(Util.class);

	public static File initDirectory(String path) {
		File result = new File(path);
		if (result.exists() && !result.isDirectory()) {
			throw new IllegalArgumentException("base path exists and not directory: " + result.getAbsolutePath());
		}
		if (!result.exists() && !result.mkdirs()) {
			throw new IllegalArgumentException("unable to create basepath: " + result.getAbsolutePath());
		}
		return result;
	}

	public static void toLog(Logger log, InputStream is) throws IOException {
		try (BufferedReader in = new BufferedReader(new InputStreamReader(is))) {
			String curLine = null;
			while ((curLine = in.readLine()) != null) {
				log.info(curLine);
			}
		}
	}

	public static void shutdown(ScheduledExecutorService executor, long timeoutMillis) {
		if (executor == null) {
			return;
		}
		executor.shutdown();
		try {
			if (!executor.awaitTermination(timeoutMillis, TimeUnit.MILLISECONDS)) {
				String threadpoolName;
				if (executor instanceof ScheduledThreadPoolExecutor) {
					ThreadFactory factory = ((ScheduledThreadPoolExecutor) executor).getThreadFactory();
					if (factory instanceof NamingThreadFactory) {
						NamingThreadFactory namingFactory = (NamingThreadFactory) factory;
						threadpoolName = namingFactory.getPrefix();
					} else {
						threadpoolName = "unknown[" + factory.getClass().getSimpleName() + "]";
					}
				} else {
					threadpoolName = "unknown[" + executor.getClass().getSimpleName() + "]";
				}
				LOG.error("executor did not terminate in the specified time: " + threadpoolName);
				executor.shutdownNow();
			}
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
			executor.shutdownNow();
		}
	}

	public static void shutdown(String name, Process process, long timeoutMillis) {
		if (process == null || !process.isAlive()) {
			return;
		}
		try {
			process.destroy();
			if (!process.waitFor(timeoutMillis, TimeUnit.MILLISECONDS)) {
				LOG.info("unable to cleanly shutdown. kill process: " + name);
				int statusCode = process.destroyForcibly().waitFor();
				if (statusCode != 0) {
					LOG.info("invalid status code while stopping: " + statusCode);
				}
			}

		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
		}
	}

	public static void deleteDirectory(File f) {
		if (f.isDirectory()) {
			for (File c : f.listFiles()) {
				deleteDirectory(c);
			}
		}
		if (!f.delete()) {
			LOG.error("Failed to delete file: " + f);
		}
	}

	private Util() {
		// do nothing
	}

}

@@ -1331,28 +1331,75 @@
 down
+Now
 ();%0A%09%09
-try %7B%0A%09%09%09if (!
+boolean cleanlyTerminated;%0A%09%09try %7B%0A%09%09%09cleanlyTerminated = 
 exec
@@ -1457,22 +1457,175 @@
 SECONDS)
+;%0A%09%09%7D catch (InterruptedException e
 ) %7B%0A%09%09
+%09
+Thread.currentThread().interrupt();%0A%09%09%09cleanlyTerminated = executor.isTerminated();%0A%09%09%7D%0A%09%09if (!cleanlyTerminated) %7B%0A%09
 %09%09String
@@ -1640,25 +1640,24 @@
 oolName;%0A%09%09%09
-%09
 if (executor
@@ -1695,25 +1695,24 @@
 Executor) %7B%0A
-%09
 %09%09%09%09ThreadFa
@@ -1784,25 +1784,24 @@
 dFactory();%0A
-%09
 %09%09%09%09if (fact
@@ -1843,17 +1843,16 @@
  %7B%0A%09%09%09%09%09
-%09
 NamingTh
@@ -1910,17 +1910,16 @@
 actory;%0A
-%09
 %09%09%09%09%09thr
@@ -1963,17 +1963,16 @@
 ();%0A%09%09%09%09
-%09
 %7D else %7B
@@ -1968,25 +1968,24 @@
 %09%09%09%7D else %7B%0A
-%09
 %09%09%09%09%09threadp
@@ -2049,17 +2049,16 @@
  + %22%5D%22;%0A
-%09
 %09%09%09%09%7D%0A%09%09
@@ -2054,25 +2054,24 @@
 %22;%0A%09%09%09%09%7D%0A%09%09%09
-%09
 %7D else %7B%0A%09%09%09
@@ -2059,33 +2059,32 @@
 %09%09%7D%0A%09%09%09%7D else %7B%0A
-%09
 %09%09%09%09threadpoolNa
@@ -2144,25 +2144,24 @@
  + %22%5D%22;%0A
-%09
 %09%09%09%7D%0A%09%09%09
 %09LOG.err
@@ -2148,25 +2148,24 @@
 %5D%22;%0A%09%09%09%7D%0A%09%09%09
-%09
 LOG.error(%22e
@@ -2238,144 +2238,8 @@
 e);%0A
-%09%09%09%09executor.shutdownNow();%0A%09%09%09%7D%0A%09%09%7D catch (InterruptedException e) %7B%0A%09%09%09Thread.currentThread().interrupt();%0A%09%09%09executor.shutdownNow();%0A
 %09%09%7D%0A

fix long-running threadpool shutdown