package code;
import java.io.IOException;
import java.time.Duration;
import java.time.LocalDateTime;

import org.json.JSONException;
import org.json.JSONObject;


public class Esecutore extends Thread {
	
	private MyQueue<Integer> codaVal; // coda in cui vengono mantenuti i valori da sommare alla variabile valore
	private int valore; // variabile numerica cumulativa inizialmente impostata a 0
	private static  int soglia;
	private Publisher publisher;
	private Automa automa;
	private Antifurto antifurto;
	private LocalDateTime tempoAllarme; //valorizzato solo quando l'allarme sta suonando. Contiene l'ora in cui l'allarme ha iniziato a suonare 
	private static boolean changedSoglia = false;
	
	public Esecutore(Publisher publisher, MyQueue<Integer> codaVal, Automa automa, Antifurto antifurto) throws JSONException, IOException {
		this.codaVal = codaVal;
		this.automa = automa;
		this.publisher = publisher;
		this.antifurto = antifurto;
		
		JSONObject statoJson = new JSONObject(Helper.leggiFile(Automa.FILE_STATO));
		this.valore = statoJson.getInt("valore");
		setSoglia(statoJson.getInt("soglia"));
		if(statoJson.getInt("stato")==2)
			this.tempoAllarme = LocalDateTime.parse(statoJson.getString("tempoAllarme"));
		
		publisher.aggiungiComando("to/gruppo2/luci/gpio", "{request:status}");
	}
	
	private int getSogliaMax() {
		return Math.round(soglia+soglia*0.2f);  // il valore non puo' andare oltre il 20 % sopra la soglia 
	}
	
	public void run() {
		final long DURATA_SUONO = 1; // l'allarme dura 1 minuti e poi smette di suonare. 
		int delta;
		int valoreToSend = valore; // ogni volta che aumento / diminuisco il valore di 5, notifico la web app pubblicando un messaggio 
		while(true) {
			while(automa.antifurtoAttivo()) { System.out.println("VALORE = "+ valore);
				delta = codaVal.receive();
				valore = valore + delta;
				if(valore < 0) 
					valore = 0;
				if(valore > getSogliaMax())
					valore = getSogliaMax();
				try {
					if(Math.abs(valore-valoreToSend) >= 5 || (valore==0 && valoreToSend!=0) || valore==getSogliaMax()) {
						JSONObject msgJson = new JSONObject();
						msgJson.put("event", valore);
						publisher.aggiungiComando("from/"+Antifurto.getMqttTree()+"/antifurto/valore", msgJson.toString());
						valoreToSend = valore;
					}
					
					JSONObject statoJson = new JSONObject(Helper.leggiFile(Automa.FILE_STATO));
					statoJson.put("valore", valore);
					if(valore >= soglia && (!automa.allarme()) && (delta>0 || changedSoglia)) { 	
						publisher.aggiungiComando("to/"+Antifurto.getMqttTree()+"/gpio/"+antifurto.getNomeOutputSuono(), "{cmd:1}");
						tempoAllarme = LocalDateTime.now();
						statoJson.put("tempoAllarme",tempoAllarme.toString());
						changedSoglia = false;
					}
					else {
						if(automa.allarme()) {
							LocalDateTime tempoAttuale = LocalDateTime.now();
							Long durata = null;
							if(tempoAllarme != null) durata = Math.abs(Duration.between(tempoAllarme, tempoAttuale).toMinutes());
							if(valore < soglia || (durata != null && durata >= DURATA_SUONO) || !automa.antifurtoAttivo() ) {
								publisher.aggiungiComando("to/"+Antifurto.getMqttTree()+"/gpio/"+antifurto.getNomeOutputSuono(), "{cmd:0}"); // l'allarme viene disattivato
							}
						}
					}
					statoJson.put("soglia", soglia);
					statoJson.put("stato", automa.getStatoAutoma());
					Helper.scriviFile(statoJson, Automa.FILE_STATO); 
				}
				catch (JSONException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
				
			}
			if(!automa.antifurtoAttivo()) {
				try {
					reset();
				} catch (JSONException | IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	
	public void aggiungiVal(int n) {
		codaVal.send(n);
	}
	
	public void reset() throws JSONException, IOException {
		valore = 0;
		codaVal.removeAll();
		JSONObject js = new JSONObject(Helper.leggiFile(Automa.FILE_STATO));
		js.put("valore", valore);
		Helper.scriviFile(js, Automa.FILE_STATO);
	}
	
	public static int getSoglia() {
		return soglia;
	}
	
	public int getValore() {
		return valore;
	}
	
	
	public static void setSoglia(int newValue) throws JSONException, IOException {
		JSONObject js = new JSONObject(Helper.leggiFile(Automa.FILE_STATO));
		js.put("soglia", newValue);
		Helper.scriviFile(js, Automa.FILE_STATO);
		soglia = newValue;
		changedSoglia = true;
	}
	
}