package vs;

import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

/**
 * client for the Smart Home application: plots graphically sensor observations
 *
 * @author Sandro Leuchter
 *
 */
public class FloorPlotter extends Frame {
	/**
	 *
	 */
	private static final long serialVersionUID = 8554414803806269611L;
	private static FloorPlotter plot;
	private static final int MAXX = 1000;
	private static final int MAXY = 600;
	private static Map<String, Color> topicColors = new HashMap<>();
	private static Color[] colors = { Color.red, Color.blue, Color.black, Color.cyan };
	private static int lastColor = 0;
	private static Color[][] plotdata = new Color[MAXX][MAXY];
	private static long start = System.currentTimeMillis();
	private static String sensorType;
	private static String floor;

	/**
	 * main routine and starting point of program. subscribes to all messages
	 * (sensor observations) on topic <tt>Conf.TOPICSTART/args[0]/+/args[1]</tt>
	 * i.e. all observations from a certain sensor type in all rooms on a certain
	 * floor.
	 *
	 * @param args[0] floor where sensor is located
	 * @param args[1] type of sensor
	 * @throws MqttException Paho library exceptions that have something to do with
	 *                       MQTT
	 * 
	 */
	public static void main(String[] args) throws MqttException {
		floor = args[0];
		sensorType = args[1];
		String topic = Conf.TOPICSTART + "/" + floor + "/+/" + sensorType;

		plot = new FloorPlotter();
		plot.setTitle("Floor Plot: " + floor);
		plot.setSize(MAXX, MAXY);
		plot.setVisible(true);

		MqttClient client = new MqttClient(Conf.BROKER, MqttClient.generateClientId());
		client.setCallback(new MqttCallback() {

			@Override
			public void connectionLost(Throwable arg0) {
			}

			@Override
			public void deliveryComplete(IMqttDeliveryToken arg0) {
			}

			@Override
			public void messageArrived(String topic, MqttMessage m) throws Exception {
				int x = (int) ((System.currentTimeMillis() - start) / 1000.0);
				try {
					double messwert = Double.valueOf(m.toString());
					int y = (int) Math.round(100.0 + (messwert * 10.0));
					String[] topicLevels = topic.split("/");
					String etage = topicLevels[1];
					String raum = topicLevels[2];
					if (!topicColors.containsKey(raum)) {
						topicColors.put(raum, colors[lastColor++]);
						System.out
								.println("Dem Plot der Etage " + etage + " wurde der " + sensorType + "-Sensor im Raum "
										+ raum + " in der Farbe " + topicColors.get(raum).toString() + " hinzugefügt.");
					}
					// System.out.format("(%3d, %3d) <- %2.2f, %s\n", x, y,
					// Double.valueOf(m.toString()), raum);
					plotdata[x][y] = topicColors.get(raum);
					plot.repaint();
				} catch (NumberFormatException e) {
					System.out.println(m); // message is not an observation:
											// will be printed out instead
				}
			}
		});
		client.connect();
		client.subscribe(topic);
		try {
			while (true) {
				Thread.sleep(1000);
			}
		} catch (InterruptedException e) {
			System.err.println(e.getMessage());
		} finally {
			try {
				client.disconnect();
			} catch (MqttException e) {
				// unrecoverable
			}
		}
	}

	/**
	 * constructor. initializes window and adds WindowListener for close event
	 */
	public FloorPlotter() {
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent ev) {
				dispose();
				System.exit(0);
			}
		});
	}

	/**
	 * @see java.awt.Frame#paint(Graphics)
	 */
	@Override
	public void paint(Graphics g) {
		for (int x = 0; x < MAXX; x++) {
			for (int y = 0; y < MAXY; y++) {
				if (plotdata[x][y] != null) {
					g.setColor(plotdata[x][y]);
					g.fillOval(x, y, 3, 3);
				}
			}
		}
	}
}
