package org.gw4e.eclipse.facade;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.StringTokenizer;
import java.util.stream.Stream;

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecuteResultHandler;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteStreamHandler;
import org.apache.commons.exec.ExecuteWatchdog;
import org.apache.commons.exec.PumpStreamHandler;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.JavaRuntime;
import org.gw4e.eclipse.message.MessageUtil;

public class ProcessFacade {

	 public static Stream<String> execute(File shell, long timeout)
			throws Exception {

		ByteArrayOutputStream out = new ByteArrayOutputStream();
		ByteArrayOutputStream err = new ByteArrayOutputStream();

		ExecuteStreamHandler streamHandler = new PumpStreamHandler(out, err, System.in);
		DefaultExecutor executor = new DefaultExecutor();
		executor.setStreamHandler(streamHandler);
		ExecuteWatchdog watchdog = new ExecuteWatchdog(timeout * 1000);
		DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
		executor.setExitValue(0);
		executor.setWatchdog(watchdog);
		String content = new String (Files.readAllBytes(shell.toPath()),Charset.forName("UTF-8"));
		 
		CommandLine cmdLine = CommandLine.parse(content);
		executor.execute(cmdLine, resultHandler);
		resultHandler.waitFor();
		
		watchdog.checkException();
		
		if (watchdog.killedProcess()) {
			Exception ex = new InterruptedException(MessageUtil.getString("timeoutofflineorcancelled"));
			Path path = Files.createTempFile("offlinedata_err", ".txt");
			Files.write(path, out.toByteArray());
			ResourceManager.logException(ex, "Process stopped. Offline data in : " + path.toFile().getAbsolutePath());
			throw new RuntimeException(ex);
		}
		
		Path path = Files.createTempFile("offlinedata", ".txt");
		Files.write(path, out.toByteArray());
  
		return  Files.lines(path).map(ProcessFacade::extract) ;
	}

	private static String extract(String s) {
		if (!s.startsWith("{\"currentElementName\":")) return "";
		StringTokenizer st = new StringTokenizer(s, ":");
		st.nextToken();
		String value = st.nextToken();
		return value.substring(1, value.lastIndexOf("\""));
	}

	private static boolean isWindows() {
		String OS = System.getProperty("os.name").toLowerCase();
		return OS.indexOf("win") >= 0;
	}

	private static String getShellCommand() {
		if (isWindows()) {
			return "cmd.exe /C ";
		}
		return "sh ";
	}

	public static File buildOfflineShellFile(IJavaProject jproject, IFile graphModel, String pathGenerator,
			String startElement) throws CoreException, IOException {
		IRuntimeClasspathEntry e = JavaRuntime.computeJREEntry(jproject);
		IVMInstall intall = JavaRuntime.getVMInstall(e.getPath());

		StringBuilder sb = new StringBuilder();
		File javaLocation = intall.getInstallLocation();

		sb.append(javaLocation.getAbsolutePath()).append(File.separator).append("bin").append(File.separator)
				.append("java").append(" -cp ").append("\"");

		String cpSeparator = "";
		String[] classpath = JavaRuntime.computeDefaultRuntimeClassPath(jproject);
		for (String cpElement : classpath) {
			sb.append(cpSeparator).append(cpElement);
			cpSeparator = System.getProperty("path.separator");
		}

		sb.append("\"").append(" org.graphwalker.cli.CLI ").append(" offline ").append(" -m ")
				.append(ResourceManager.toFile(graphModel.getFullPath()).getAbsolutePath()).append(" \"")
				.append(pathGenerator).append("\" ").append(" -e ").append(startElement).append(" --verbose ");

		 
		String extension = isWindows() ? "bat" : "sh";

		Path path = Files.createTempFile("offlineShellRunner", "." + extension);

		Files.write(path, sb.toString().getBytes(StandardCharsets.UTF_8));

		File file = path.toFile();
		 
		ResourceManager.logInfo(jproject.getProject().getName(), "Shell file : " + file.getAbsolutePath());
		return file;
	}

}

@@ -938,16 +938,87 @@
 eUtil;%0A%0A
+import com.google.gson.JsonObject;%0Aimport com.google.gson.JsonParser;%0A%0A
 public c
@@ -2445,73 +2445,104 @@
 %7D%0A%0A%09
-private static String extract(String s) %7B%0A%09%09if (!s.startsWith(%22%7B%5C
+ %0A%09// %7B%22modelName%22:%22Simple%22,%22data%22:%5B%5D,%22currentElementID%22:%22b5fceb6b-d831-4528-acea-e53a6f3c3e7b%22,
 %22cur
@@ -2560,182 +2560,393 @@
 Name
-%5C
 %22:%22
-)) return %22%22;%0A%09%09StringTokenizer st = new StringTokenizer(s, %22:%22);%0A%09%09st.nextToken();%0A%09%09String value = st.nextToken();%0A%09%09return value.substring(1, value.lastIndexOf(%22%5C%22%22));
+v_VerifyAppRunning%22,%22properties%22:%5B%7B%22blocked%22:false%7D,%7B%22gw.vertex.init.script%22:%22%22%7D,%7B%22x%22:206%7D,%7B%22width%22:100%7D,%7B%22y%22:190%7D,%7B%22description%22:%22%22%7D,%7B%22height%22:100%7D%5D%7D%0A%09%0A%09private static String extract(String json) %7B%0A%09%09JsonParser parser = new JsonParser();%0A%09%09JsonObject rootObj = parser.parse(json).getAsJsonObject();%0A%09%09String name = rootObj.get(%22currentElementName%22).getAsString();%0A%09%09return  name ; 
 %0A%09%7D%0A

fix offline parsing result