package code;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
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.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

//import scenari.Automa;
//import scenari.Scenari;

public class Subscriber implements MqttCallback{

	private Luci luci;
	private Esecutore esec;
	public String sensM;
	
	public Subscriber(Luci luci, Esecutore esec, String sensm) {
		this.luci=luci;
		this.esec = esec;
		this.sensM = sensm;
	}

	@Override
	public void connectionLost(Throwable arg0) {
		Helper.print("connessione persa\t"+arg0);
		final Date d = new Date();
		Date d2 = new Date();
		long time = Math.abs(d2.getTime()-d.getTime());

		while (time<600000) {
			try {
				Helper.print("retrying...");

				Luci.main(null);
				return;
			} catch (MqttException | JSONException | IOException e) {
				Helper.print("non sono riusciuto");
				d2 = new Date();
				time = Math.abs(d2.getTime()-d.getTime());
			}
		}
		Helper.print("fuori dal while");
		if(time>=600000) {
			Helper.print("Tentativo di riconnessione fallito");
			System.exit(1);
		}
	}


	@Override
	public void deliveryComplete(IMqttDeliveryToken arg0) {
		Helper.print("inviato");
	}

	@Override
	public void messageArrived(String topic, MqttMessage message) throws MqttException, JSONException, IOException {
				
		Helper.print("new message: "+topic+"  "+message.toString());
		
		if(topic.equals(Luci.getMqttTree("rpc/","luci"))) {
			Helper.print("invio la mia configurazione");
			sendFile(Luci.getMqttTree("from/","luci"),true);
			return;
		}
		
		if(topic.equals("to/all")) {
			Helper.print("invio il mio stato");
			sendStatus(Luci.getMqttTree("from/","luci"),true);
			return;
		}

		JSONObject msgJson = new JSONObject(message.toString());

		//la beaglebone risponde sutopic {"event":1} se è acceso, 0 altrimenti
		
		if(topic.equals(Luci.getMqttTree("to", "luci/new"))){
	
			JSONObject config = new JSONObject(Helper.leggiFile(Luci.FILE_ZONA));
			
			String nome= msgJson.getString("nome");
			for(Luce k: Luci.luciList) {
				if(k.getNome().equalsIgnoreCase(nome)) {
					
					//luci.sendMqttMessage(topic, topic)//che ci scrivo se fallisco?
					
					//rispondi impossibile su topic
					System.out.println("Nome gia' presente, inserimento annullato\n");
					
					return;
				}
			}
			int k=Luci.luciList.size();
			config.put("lamp"+k, msgJson);
			Luci.luciList.add(new Luce(msgJson));//,"lamp"+k
			Helper.scriviFile(config, Luci.FILE_ZONA);
		}
		
		if(topic.equals(Luci.getMqttTree("to", "luci/sensore"))){
			//salvati il sensore di movimento
			
			sensM=msgJson.getString("sensM");
			//devo aggiornare in file
			JSONObject config = new JSONObject(Helper.leggiFile(Luci.FILE_ZONA));
			config.put("sensM", sensM);
			Helper.scriviFile(config, Luci.FILE_ZONA);
			
			
		}//gruppo2/luci/luci/sensore
		
		
		
		//controllo i topic su cui mi arrivano gli on/off
		if(topic.startsWith(Luci.getMqttTree("from", "luci/gpio/IN"))){
			//prendo l'ultimo pezzo del topic, diventa il mio nome
			
			String pezzo =topic.substring(23);//seleziono solo il nome della lamp
			System.out.println("nome lamp\t"+pezzo);
			
			for(int i=0;i<Luci.luciList.size();i++) {
				if(Luci.luciList.get(i).getIN().equalsIgnoreCase(pezzo) && msgJson.has("event") && msgJson.getInt("event")==1) {//non è k.getIN()?
					
					String req=Luci.luciList.get(i).getStato() ? "{cmd:0}":"{cmd:1}";
					
					
//					if(Luci.luciList.get(i).getStato()) {
//						req = "{cmd:0}";
//					//topic corretto? poi risponde, se risposta è ok allora setto stato e scrivo
//					}
//					else {req="{cmd:1}";}
					
					luci.sendMqttMessage(luci.getMqttTree("to", "gpio/" + Luci.luciList.get(i).getOUT()), req);
					//to/gruppo2/luci/gpio/OUTn
					//JSON {cmd:1} o 0 accendi/spegni
					
					Luci.luciList.get(i).setStato(!Luci.luciList.get(i).getStato());
					
					JSONObject config = new JSONObject(Helper.leggiFile(Luci.FILE_ZONA));
					
					JSONObject lux=new JSONObject();
					lux.put("nome", Luci.luciList.get(i).getNome());
					lux.put("stato", Luci.luciList.get(i).getStato());
					lux.put("input", Luci.luciList.get(i).getIN());
					lux.put("output", Luci.luciList.get(i).getOUT());
					
					config.put("lamp"+i, lux);
					
					Helper.scriviFile(config, Luci.FILE_ZONA);
					
					
				}
			}
			//sensM tempo
			if(topic.startsWith(Luci.getMqttTree("from", "luci/gpio/IN"))){
				//prendo l'ultimo pezzo del topic, diventa il mio nome
				String nomeSensM =topic.substring(23);//seleziono solo il nome della lamp
				System.out.println("nome lamp\t"+pezzo);
				if(nomeSensM==sensM) {
					Esecutore es=new Esecutore(luci);
					es.run();
				}
				
			}
					
		}//gruppo2/luci/luci/sensore
		
		Helper.print("Impossibile");
	}
	
	private void sendFile(String topic,boolean moreInfo) throws MqttException, JSONException, IOException {
		JSONObject j = new JSONObject(luci.FILE_ZONA);
		//System.out.println(luci.FILE_ZONA);
		
		//j.put("stato", luci.luciList.toString());
		luci.sendMqttMessage(topic, j.toString());
	}
	
	private void sendStatus(String topic,boolean moreInfo) throws MqttException, JSONException, IOException {
		JSONObject j = new JSONObject(luci.FILE_ZONA);
		j.remove("sensM");
		//System.out.println(luci.FILE_ZONA);
		
		//j.put("stato", luci.luciList.toString());
		luci.sendMqttMessage(topic, j.toString());
	}



}