package be.uantwerpen.ansymo.semanticadaptation.cg.cpp.tests;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;

import org.apache.commons.io.IOUtils;

public class CMakeUtil
{
	private static String OS = System.getProperty("os.name").toLowerCase();

	private boolean verbose = true;

	public CMakeUtil( boolean verbose)
	{
		this.verbose = verbose;
	}

	

	public static class CMakeGenerateException extends Exception
	{

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		public final String errors;

		public CMakeGenerateException(String errors)
		{
			super(errors);
			this.errors = errors;
		}
	}

	public boolean generate(File root) throws IOException,
			InterruptedException, CMakeGenerateException
	{
		String cmake = "cmake";

		if (isMac())
		{
			cmake = "/usr/local/bin/cmake";
		}

		ProcessBuilder pb = new ProcessBuilder(cmake,"-DCMAKE_BUILD_TYPE=Debug", ".");
		pb.directory(root);

		return runProcess(pb, verbose);

	}

	public boolean make(File root, String... goal) throws IOException,
			InterruptedException, CMakeGenerateException
	{
		String make = "make";

		ProcessBuilder pb = new ProcessBuilder(make, "-j3");
		for (String string : goal)
		{
			pb.command().add(string);
		}
		pb.directory(root);

		return runProcess(pb, verbose);

	}

	public boolean run(File root, String cmd, boolean verbose)
			throws IOException, InterruptedException, CMakeGenerateException
	{

		String name = cmd;

		if (isWindows())
		{
			name = name + ".exe";
		} else
		{
			name = "./" + name;
		}

		ProcessBuilder pb = new ProcessBuilder(name);
		pb.directory(root);

		return runProcess(pb, verbose);

	}

	public boolean runProcess(ProcessBuilder pb, boolean verbose)
			throws IOException, InterruptedException, CMakeGenerateException
	{
		final Process p = pb.start();

		if (verbose)
		{
			Thread outThread = new Thread(new Runnable()
			{

				@Override
				public void run()
				{
					BufferedReader out = new BufferedReader(new InputStreamReader(p.getInputStream()));

					String tmp = null;
					try
					{
						while ((tmp = out.readLine()) != null)
						{
							System.out.println(tmp);
						}
					} catch (IOException e)
					{
						return;
					}
				}
			});

			outThread.setDaemon(true);
			outThread.start();
		}

		p.waitFor();
		
		List<String> errors = IOUtils.readLines(p.getErrorStream());

		boolean res = p.exitValue() == 0;

		if (!res)
		{
			if (!errors.isEmpty())
			{
				StringBuffer sb = new StringBuffer();
				for (String string : errors)
				{
					sb.append(string);
					sb.append("\n");
				}
				throw new CMakeGenerateException(sb.toString());
			}
		}
		return res;
	}

	public static boolean isMac()
	{

		return OS.indexOf("mac") >= 0;

	}

	public static boolean isWindows()
	{

		return OS.indexOf("win") >= 0;

	}

	public static boolean isUnix()
	{

		return OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0
				|| OS.indexOf("aix") > 0;

	}

	public boolean isVerbose() {
		return verbose;
	}

	public void setVerbose(boolean verbose) {
		this.verbose = verbose;
	}
}
