package de.hottis.MeasurementCollector;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Properties;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;



public class MqttReceiver {
	final protected Logger logger = LogManager.getRootLogger();

	static final String MQTT_BROKER_PROP = "mqtt.broker";
	static final String MQTT_CLIENTID_PROP = "mqtt.clientid";
	static final String MQTT_USERNAME_PROP = "mqtt.username";
	static final String MQTT_PASSWORD_PROP = "mqtt.password";
	
	
	class Listener implements IMqttMessageListener {
		public void messageArrived(String topic, MqttMessage payload) {
			parsers.get(topic).execute(LocalDateTime.now(), payload.toString());
		}
	}
	
	private final String broker;
	private final String clientId;
	private final MqttConnectOptions connOpts;
	private MqttClient client;
	private HashMap<String, AMessageParser> parsers;
	private final Listener listener = new Listener();
	
	public MqttReceiver(Properties config) {
		broker = config.getProperty(MQTT_BROKER_PROP, "localhost");
		clientId = config.getProperty(MQTT_CLIENTID_PROP, "MeasurementCollector.MqttReceiver");
		connOpts = new MqttConnectOptions();
		String username = config.getProperty(MQTT_USERNAME_PROP);
		String password = config.getProperty(MQTT_PASSWORD_PROP);
		if (username != null && password != null) {
			connOpts.setUserName(username);
			connOpts.setPassword(password.toCharArray());
		}
		
		parsers = new HashMap<String, AMessageParser>();
	}
	
	public void connect() throws MeasurementCollectorException {
		try {
			client = new MqttClient(broker, clientId);
			client.connect(connOpts);
			logger.info("Connected");
		} catch (MqttException e) {
			throw new MeasurementCollectorException("MqttReceiver.connect", e);
		}
	}
	
	public void registerParser(AMessageParser parser) throws MeasurementCollectorException {
		try {
			parsers.put(parser.getTopic(), parser);
			client.subscribe(parser.getTopic(), listener);
			logger.info("Subscribed: " + parser.getTopic());
		} catch (MqttException e) {
			throw new MeasurementCollectorException("MqttReceiver.registerParser", e);
		}
	}
}
