import java.util.Date;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.json.JSONException;
import org.json.JSONObject;

public class SubscribeCallback implements MqttCallback{
	
	private Antifurto client;
	private Publisher publisher;
	private String nomeInterruttore; 
	private String nomeOutputSuono;
	private Esecutore esec;
	private Automa automa;
	
	public SubscribeCallback(Antifurto client, Publisher publisher, String nomeInterruttore, String nomeOutputSuono, Esecutore esec, Automa automa) {
		this.client = client;
		this.publisher = publisher;
		this.nomeInterruttore = nomeInterruttore;
		this.nomeOutputSuono = nomeOutputSuono;
		this.esec = esec;
		this.automa = automa;
	}

	@Override
	public void connectionLost(Throwable arg0) {
		boolean retry = true;
		final Date d = new Date();
		Date d2 = new Date();
		long time = Math.abs(d2.getTime()-d.getTime());
		while(retry & (time<600000)) {
			try {
				client.startClient(esec, publisher);
				retry = false;
			} catch (MqttException e) {
				d2 = new Date();
				time = Math.abs(d2.getTime()-d.getTime());
			}
		}
		if(time>=600000) {
			System.out.println("Tentativo di riconnessione fallito");
			System.exit(1);
		}
	}

	
	@Override
	public void deliveryComplete(IMqttDeliveryToken arg0) {
		// Nessuna operazione
		
	}
	

	@Override
	public void messageArrived(String topic, MqttMessage message) throws Exception {
		if(topic.equals("to/all"))
			sendDescription("from/gruppo2/luci/antifurto/description");
		else {
			if(topic.equals("rpc/gruppo2/luci/antifurto"))
				sendMyState("from/gruppo2/luci/antifurto"); // CONTROLLA SE VA BENE PUBBLICARE LO STATO SU QUESTO TOPIC O SE IL TOPIC DEVE ESSERE UN'ALTRO. NOTA: NON POSSO PUBBLICARE SULLO STESSO TOPIC CHE HO SOTTOSCRITTO
			else {
				JSONObject msgJson = new JSONObject(message.toString());
				
				
				// CONTROLLA SULLA BEAGLEBONE CHE IL MESSAGGIO MANDATO SIA UN INT. CONTROLLA ANCHE IL TOPIC SU CUI MANDA I MESSAGGI (da aver sottoscritto i topic correttamente)
				
				if(topic.equals("from/gruppo2/luci/gpio/"+nomeOutputSuono)) {
					int newStatus = -1;
					if(msgJson.has("status"))
						newStatus = msgJson.getInt("status");
					else {
						if(msgJson.has("event"))
							newStatus = msgJson.getInt("event");
					}
					handleStateMsgFromOutputSuono(newStatus);
				}
				else {
					int event = msgJson.getInt("event");
					if(event==0) {
						// e' stato premuto l'interruttore / il sensore di movimento ha rilevato qualcuno
						if(topic.equals("from/gruppo2/luci/gpio/"+nomeInterruttore))
							handleStateMsgFromInterruttore();
						else {
							// il topic sara' from/gruppo2/luci/gpio/IN0  dove IN0 e' un sensore di movimento
							String[] t = topic.split("/");
							handleMovimento(t[4]);
						}
					}
				}				
			}
		}	
		
	}
	

	
	private synchronized void handleStateMsgFromInterruttore() throws JSONException {
		automa.changeStatoInterruttore();
		if(automa.getStatoInterruttore().equals("off")) {
			publisher.aggiungiComando("to/gruppo2/luci/gpio/"+nomeOutputSuono, "{cmd:0}"); 
			esec.reset();
		}
	}
	
	
	private synchronized void handleStateMsgFromOutputSuono(int newStatus) throws JSONException {
		if(newStatus!=-1) {
			String statusOnOff = automa.converter(newStatus); // lo stato e' della forma "on" oppure "off"
			if(! statusOnOff.equals(automa.getStatoSuono()) ) {
				automa.aggiornaStatoSuono(statusOnOff);
			}
		}
	}
	

	
	
	private void handleMovimento(String nomeSensore) {
		if(automa.getStatoInterruttore().equals("on"))
			esec.aggiungiVal(automa.getDelta(nomeSensore));
	}
	
	private void sendMyState(String topic) throws MqttException {
		publisher.aggiungiComando(topic, "{\"status\":"+automa.getStatoAutoma()+"}"); 
	}
	
	private void sendDescription(String topic) {
		// DA FARE: guardare quale descrizione manda netmon, archiver, meter,... e implementare di conseguenza questo metodo
//		String msg = 
//		publisher.aggiungiComando(topic, msg); 
	}
	

}