package de.ugoe.cs.eventbench.jfcmonitor;

import java.awt.AWTEvent;
import java.awt.event.AWTEventListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.swing.JComponent;

public class JFCListener implements AWTEventListener {

	final static String ENDLINE = System.getProperty("line.separator"); 
	
	final OutputStreamWriter outputWriter;
	
	public JFCListener(OutputStreamWriter outputWriter) {
		this.outputWriter = outputWriter;
	}
	
	@Override
	public void eventDispatched(AWTEvent event) {
		StringBuilder builder = new StringBuilder();
				
		if( event instanceof MouseEvent ) {
			MouseEvent mouseEvent = (MouseEvent) event;
			if( !isMouseMovement(event.getID()) ) {
				builder.append("<event id=\"" + event.getID() + "\">" + ENDLINE);
				builder.append(" <param name=\"X\" value=\"" + mouseEvent.getX() + "\" />" + ENDLINE);
				builder.append(" <param name=\"Y\" value=\"" + mouseEvent.getY() + "\" />" + ENDLINE);
				builder.append(" <param name=\"Button\" value=\"" + mouseEvent.getButton() + "\" />" + ENDLINE);
				builder.append(" <param name=\"Modifiers\" value=\"" + mouseEvent.getModifiers() + "\" />" + ENDLINE);
				addSourceInfo(builder, event);
				builder.append("</event>" + ENDLINE);
			}
		}
		if( event instanceof KeyEvent ) {
			KeyEvent keyEvent = (KeyEvent) event;
			if( keyEvent.getID()==KeyEvent.KEY_TYPED ) {
				builder.append("<event id=\"" + event.getID() + "\">" + ENDLINE);
				builder.append(" <param name=\"KeyCode\" value=\"" + keyEvent.getKeyCode() + "\" />" + ENDLINE);
				builder.append(" <param name=\"Modifiers\" value=\"" + keyEvent.getModifiers() + "\" />" + ENDLINE);
				addSourceInfo(builder, event);
				builder.append("</event>" + ENDLINE);
			}
		}
		if( builder.length()>0 && outputWriter!=null ) {
			try {
				outputWriter.write(builder.toString());
				outputWriter.flush();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	private void addSourceInfo(StringBuilder builder, AWTEvent event) {
		builder.append(" <param name=\"Source\" value=\"" + event.getSource().toString() + "\" />" + ENDLINE);
		if( event.getSource() instanceof JComponent ) {
			JComponent source = (JComponent) event.getSource();
			builder.append(" <param name=\"SourceName\" value=\"" + source.getName() + "\" />" + ENDLINE);
			for(Method method : source.getClass().getMethods() ) {
				try {
					if( method.getName()=="getText" ) {
						String text = (String) method.invoke(source, new Object[]{});
						builder.append(" <param name=\"SourceText\" value=\"" + text + "\" />" + ENDLINE);
					}
					if( method.getName()=="getTitle" ) {
						String title = (String) method.invoke(source, new Object[]{});
						builder.append(" <param name=\"SourceTitle\" value=\"" + title + "\" />" + ENDLINE);
					}
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				} catch (InvocationTargetException e) {
				}
			}
			/* TODO should include info about parent
			builder.append(" <param name=\"Parent\" value=\"" + source.getParent().toString() + "\" />" + ENDLINE);
			builder.append(" <param name=\"ParentName\" value=\"" + source.getParent().getName() + "\" />" + ENDLINE);
			*/
		}
	}
	
	private boolean isMouseMovement(int eventId) {
		return eventId==MouseEvent.MOUSE_MOVED || eventId==MouseEvent.MOUSE_DRAGGED || eventId==MouseEvent.MOUSE_ENTERED || eventId==MouseEvent.MOUSE_EXITED;
	}

}
