import ij.IJ;
import ij.gui.GenericDialog;
import ij.io.SaveDialog;

import fiji.User_Plugins;

import imagej.util.LineOutputStream;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import java.io.File;
import java.io.PrintStream;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

import org.scijava.util.ReadInto;

discoverVLC() {
	if (System.getProperty("os.name").startsWith("Windows")) {
		vlc = "C:\\Program Files\\VideoLAN\\VLC\\vlc.exe";
		if (new File(vlc).exists())
			return vlc;
		vlc = "C:\\Program Files (x86)\\VideoLAN\\VLC\\vlc.exe";
		if (new File(vlc).exists())
			return vlc;
	}
	else
		for (String dir : System.getenv("PATH").split(":")) {
			file = new File(dir, "vlc");
			if (file.exists())
				return file.getAbsolutePath();
		}
		if (System.getProperty("os.name").startsWith("Mac")) {
			file = new File("/Applications/VLC.app/Contents/MacOS/", "VLC");
			if (file.exists())
				return file.getAbsolutePath();
		}
	return null;
}

getOutputFile() {
	if (IJ.getInstance() != null) {
		SaveDialog od = new SaveDialog("Save screencast as...", null, ".ogv");
		directory = od.getDirectory();
		fileName = od.getFileName();
		if (directory == null || fileName == null)
			return null;
		return new File(directory, fileName);
	}
	else if (bsh.args.length > 0)
		return new File(bsh.args[0]);
	return null;
}

class IJLogOutputStream extends LineOutputStream {
	void println(String line) {
		IJ.log(line);
	}
}

startScreencast(vlc, outputFile, width) {
	outputPath = outputFile.getAbsolutePath();
	IJ.showStatus("Screencasting to '" + outputFile + "'");
	mux = "avi";
	vcodec = "mp4v";
	if (outputFile.getName().endsWith(".ogv")) {
		mux = "ogg";
		vcodec = "theora";
	}
	else if (outputFile.getName().endsWith(".mov")) {
		mux = "mov";
		vcodec = "h264";
	}
	Process process = Runtime.getRuntime().exec(new String[] {
		vlc,
		"-I", "dummy",
		//"-vvv",
		"screen://:screen-fps=15",
		"--sout=#transcode{"
			+ "vcodec=" + vcodec + ","
			+ "vb=800,"
			+ "width=" + width + ","
			+ "acodec=vorb,"
			+ "ab=128,"
			+ "channels=2,"
			+ "samplerate=22050"
		+ "}:standard{"
			+ "access=file,"
			+ "mux=" + mux + ","
			+ "dst='" + outputPath + "'"
		+ "}",
		"vlc://quit"
	}, null, null);
	process.getOutputStream().close();
	out = new PrintStream(new IJLogOutputStream());
	err = new ReadInto(process.getErrorStream(), out);
	out = new ReadInto(process.getInputStream(), out);

	item = User_Plugins.getMenuItem("File>Make Screencast");
	if (item != null) {
		ij = IJ.getInstance();
		listeners = item.getActionListeners();
		for (ActionListener listener : listeners)
			item.removeActionListener(listener);
		actionListener = new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				item.removeActionListener(this);
				IJ.showStatus("Stopping screencast");
				process.destroy();
				err.interrupt();
				err.join();
				out.interrupt();
				out.join();
				IJ.showStatus("Saved '" + outputFile + "'");
				if (ij == null)
					System.exit(0);
				for (ActionListener listener : listeners)
					item.addActionListener(listener);
				item.setLabel("Make Screencast");
			}
		};
		item.setLabel("Stop Screencast");
		item.addActionListener(actionListener);
	}
}

run() {
	vlc = discoverVLC();
	if (vlc == null) {
		IJ.error("Could not find VLC, please install");
		IJ.runPlugIn("ij.plugin.BrowserLauncher", "http://www.videolan.org/index.html");
		return;
	}

	outputFile = getOutputFile();
	if (outputFile == null)
		return; // canceled
	if (outputFile.exists() && outputFile.length() != 0 &&
			!IJ.showMessageWithCancel("Overwrite?", "The file '" + outputFile + "' appears to exist already. Overwrite?"))
		return;

	if (IJ.getInstance() != null)
		width = (int)IJ.getNumber("Width", Toolkit.getDefaultToolkit().getScreenSize().width);
	else if (bsh.args.length > 1)
		width = Integer.parseInt(bsh.args[1]);
	else
		width = 640;

	startScreencast(vlc, outputFile, width);
}

run();
