package org.protocjar;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Protoc
{
	public static void main(String[] args) {
		try {
			runProtoc(args);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static int runProtoc(String[] args) throws IOException, InterruptedException {
		File protocTemp = extractProtoc();
		
		List<String> protocCmd = new ArrayList<String>();
		protocCmd.add(protocTemp.getAbsolutePath());
		protocCmd.addAll(Arrays.asList(args));
		ProcessBuilder pb = new ProcessBuilder(protocCmd);
		log("executing: " + protocCmd);
		
		Process protoc = pb.start();
		new Thread(new StreamCopier(protoc.getInputStream(), System.out)).start();
		new Thread(new StreamCopier(protoc.getErrorStream(), System.err)).start();
		int exitCode = protoc.waitFor();
		
		if (protocTemp != null) protocTemp.delete();
		return exitCode;
	}

	static File extractProtoc() throws IOException {
		String protocStr = "protoc";
		String resourcePath = null; // for jar
		String filePath = null; // for test

		String osName = System.getProperty("os.name").toLowerCase();
		if (osName.startsWith("win")) {
			resourcePath = "/bin/win32/" + protocStr + ".exe";
			filePath = sProtocFilePath + "/win32/" + protocStr + ".exe";
		}
		else if (osName.startsWith("linux")) {
			resourcePath = "/bin/linux/";
			filePath = sProtocFilePath + "/linux/";
		}
		else if (osName.startsWith("mac")) {
			resourcePath = "/bin/mac/";
			filePath = sProtocFilePath + "/mac/";
		}
		else {
			throw new IOException("Unsupported platform: " + osName);
		}
		
		Class<Protoc> clazz = Protoc.class;
		InputStream is = clazz.getResourceAsStream(resourcePath);
		if (is == null) is = new FileInputStream(filePath);
		
		File temp = File.createTempFile(protocStr, ".exe");
		temp.setExecutable(true);
		FileOutputStream os = new FileOutputStream(temp);
		streamCopy(is, os);
		is.close();
		os.close();
		return temp;
	}

	static void streamCopy(InputStream in, OutputStream out) throws IOException {
		int read = 0;
		byte[] buf = new byte[4096];
		while ((read = in.read(buf)) > 0) out.write(buf, 0, read);		
	}

	static void log(String msg) {
		System.out.println("protoc-jar: " + msg);
	}

	static class StreamCopier implements Runnable
	{
		public StreamCopier(InputStream in, OutputStream out) {
			mIn = in;
			mOut = out;
		}

		public void run() {
			try {
				streamCopy(mIn, mOut);
			}
			catch (IOException e) {
				e.printStackTrace();
			}
		}

		private InputStream mIn;
		private OutputStream mOut;
	}

	static String sProtocFilePath = "bin_241";
}

@@ -1121,39 +1121,8 @@
 n %7B%0A
-%09%09String protocStr = %22protoc%22;%0A
 %09%09St
@@ -1324,33 +1324,22 @@
 n/win32/
-%22 + 
 protoc
-Str + %22
 .exe%22;%0A%09
@@ -1381,25 +1381,14 @@
 n32/
-%22 + 
 protoc
-Str + %22
 .exe
@@ -1461,24 +1461,30 @@
 %22/bin/linux/
+protoc
 %22;%0A%09%09%09filePa
@@ -1514,16 +1514,22 @@
 %22/linux/
+protoc
 %22;%0A%09%09%7D%0A%09
@@ -1590,24 +1590,30 @@
 = %22/bin/mac/
+protoc
 %22;%0A%09%09%09filePa
@@ -1641,16 +1641,22 @@
 + %22/mac/
+protoc
 %22;%0A%09%09%7D%0A%09
@@ -1924,17 +1924,16 @@
 ile(
+%22
 protoc
-Str
+%22
 , %22.

fix protoc path