package com.github.bhaak;

import com.amazon.kindle.kindlet.AbstractKindlet;
import com.amazon.kindle.kindlet.KindletContext;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

public class HackedUpReaderKindlet extends AbstractKindlet {

	private static final Logger logger = Logger.getLogger(HackedUpReaderKindlet.class);
	private final String hackedupreader = "/mnt/us/hackedupreader/bin/cr3";

	private Process hackedupreaderProcess;
	private HackedUpReaderWaitThread thread = null;

	public void create(KindletContext context) {
		Properties p = new Properties();
		try {
			p.load(this.getClass().getResource("log4j.properties").openStream());
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		PropertyConfigurator.configure(p);
		
		logger.info("create()");
	}

	public void start() {
		try {
			logger.info("Starting HackedUpReader");
			
			// Start HackedUpReader
			hackedupreaderProcess = Runtime.getRuntime().exec(hackedupreader);
			logger.info("Started HackedUpReader "+hackedupreaderProcess);
			
			thread = new HackedUpReaderWaitThread();
			thread.start();
		} catch (Throwable t) {
			logger.error(t.getMessage(), t);
		}
	}


	public void stop() {
		logger.info("stop()");
		// Stop HackedUpReader
		if (hackedupreaderProcess != null) {
			try {
				thread.interrupt();
				killQuitProcess(hackedupreaderProcess);
			} catch (Exception e) {
				logger.error(e.toString(), e);
			}
		}
		super.stop();
	}
	
	public void destroy() {
		logger.info("destroy()");
		super.destroy();
	}

	/** 
	 * Send a QUIT signal to a process.
	 * 
	 * See http://stackoverflow.com/questions/2950338/how-can-i-kill-a-linux-process-in-java-with-sigkill-process-destroy-does-sigte#answer-2951193
	 */
	private void killQuitProcess(Process process)
			throws InterruptedException, IOException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
		if (process.getClass().getName().equals("java.lang.UNIXProcess")) {
			Class cl = process.getClass();
			Field field = cl.getDeclaredField("pid");
			field.setAccessible(true);
			Object pidObject = field.get(process);

			Runtime.getRuntime().exec(new String[]{"/bin/kill", "-QUIT", pidObject.toString()}).waitFor();
		} else {
			throw new IllegalArgumentException("Needs to be a UNIXProcess");
		}
	}

	/** This thread waits for HackedUpReader to finish and then sends
	 * a BACKWARD lipc event. 
	 */
	class HackedUpReaderWaitThread extends Thread {
		public void start() {
			logger.info("HackedUpReaderWaitThread started");
			super.start();
		}
		public void run() {
			try {
				logger.info("HackedUpReaderWaitThread run");

				// wait for HackedUpReader to finish
				hackedupreaderProcess.waitFor();
				logger.info("HackedUpReader stopped");

				// sent BACKWARD lipc event if HackedUpReader finished normally
				Runtime.getRuntime().exec(new String[]{"/usr/bin/lipc-set-prop", "com.lab126.appmgrd", "backward", "0"});
			} catch (IOException e) {
				logger.error(e.toString(), e);
			} catch (InterruptedException e) {
				// Thread got interrupted, don't send lipc event
				logger.warn(e.toString());
			}
		}
	}
}

@@ -120,16 +120,102 @@
 ntext;%0A%0A
+import java.awt.BorderLayout;%0Aimport java.awt.Container;%0Aimport javax.swing.JButton;%0A%0A
 import j
@@ -686,16 +686,53 @@
  null;%0A%0A
+%09JButton status = new JButton(%22!%22);%0A%0A
 %09public 
@@ -769,16 +769,19 @@
 text) %7B%0A
+%09%09%0A
 %09%09Proper
@@ -1025,34 +1025,202 @@
 %22);%0A
-%09%7D%0A%0A%09public void start() %7B
+%0A%09%09// set up button%0A%09%09Container root = context.getRootContainer();%0A%09%09root.setLayout(new BorderLayout());%0A%09%09root.add(status, BorderLayout.CENTER);%0A%09%09status.setText(%22loading HackedUpReader ...%22);%0A
 %0A%09%09t
@@ -1267,20 +1267,16 @@
 ader%22);%0A
-%09%09%09%0A
 %09%09%09// St
@@ -1433,12 +1433,8 @@
 s);%0A
-%09%09%09%0A
 %09%09%09t
@@ -1525,91 +1525,290 @@
 %0A%09%09%09
-logger.error(t.getMessage(), t);%0A%09%09%7D%0A%09%7D%0A%0A%0A%09public void stop() %7B%0A%09%09logger.info(%22stop
+status.setText(%22Error while loading HackedUpReader%22);%0A%09%09%09logger.error(t.getMessage(), t);%0A%09%09%7D%0A%09%7D%0A%0A%09public void start() %7B%0A%09%09logger.info(%22start()%22);%0A%09%09super.start();%0A%09%7D%0A%0A%09public void stop() %7B%0A%09%09logger.info(%22stop()%22);%0A%09%09super.stop();%0A%09%7D%0A%0A%09public void destroy() %7B%0A%09%09logger.info(%22destroy
 ()%22)
@@ -2025,82 +2025,8 @@
 %09%09%7D%0A
-%09%09super.stop();%0A%09%7D%0A%09%0A%09public void destroy() %7B%0A%09%09logger.info(%22destroy()%22);%0A
 %09%09su

Move starting and stopping HackedUpReader into create()/destroy()