package scenari;

import java.io.IOException;
import java.util.Iterator;

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

import utility.Esecutore;
import utility.Helper;

public class Automa {
//	0: learn = off, antifurto = off
//	1: learn = on, antifurto = off
//	2: learn = off, antifurto = on => scenari = on

	private int stato;
	private JSONObject jsonObject;
	private boolean learn;
	private boolean antifurto;
	private final String DATABASE_PATH = "./scenari.json";
	public boolean unreadStatus = false;

	public Automa() throws JSONException, IOException {
		this.jsonObject = new JSONObject(Helper.leggiFile(DATABASE_PATH));
		setCollaterals(this.jsonObject.getInt("stato-attuale"));
	}
	
	public synchronized void setStato(String command) {
		setStato(command,false);
	}

	public synchronized void setStato(String command,boolean fromDatabase) {
		if (command == null || !Helper.checkJSON(command)
				|| (!command.contains("\"learn\":") && !command.contains("\"antifurto\":"))
				|| (!command.contains(":\"on\"") && !command.contains(":\"off\"")))
			return;
		String[] cmd = command.split(":");
		String cosa = cmd[0].split("\"", 3)[1];
		String come = cmd[1].split("\"", 3)[1];

		if (Helper.compareText(cosa, "learn")) {
			if (Helper.compareText(come, "on") && this.stato == 0) {
				setCollaterals(1,!fromDatabase);
			} else if (Helper.compareText(come, "off") && this.stato == 1) {
				setCollaterals(0,!fromDatabase);
			}
			return;
		}
		if (Helper.compareText(cosa, "antifurto")) {
			if (Helper.compareText(come, "on") && this.stato == 0) {
				setCollaterals(2,!fromDatabase);
			} else if (Helper.compareText(come, "off") && this.stato == 2) {
				setCollaterals(0,!fromDatabase);
			}
			return;
		}
	}
	
	public String findPossibleCommand(String which) throws JSONException{
		Boolean learn = null;
		if(!(learn=Helper.compareText(which, "learn")) && !Helper.compareText(which, "antifurto"))
			return null;
//		devo cercare nel jsonObject lo stato attuale e trovare la stringa corrispondente al which, poi discriminare in base a cio' che mi permette di cambiare stato
		@SuppressWarnings("unchecked")
		Iterator<String> keys = jsonObject.keys();
		while(keys.hasNext()) {
			String key = keys.next();
			try {
				JSONArray array = jsonObject.getJSONArray(key);
				for(int i =0; i<array.length(); i++) {
					JSONObject a = array.getJSONObject(i);
					int stato = a.getInt("stato");
					if(stato != this.stato)
						continue;
					if(learn) {
						int learnOff = a.getInt("learn-off");
						if(learnOff != stato)
							return "off";
						int learnOn = a.getInt("learn-on");
						if(learnOn != stato)
							return "on";
					} else {
						int antifurtoOff = a.getInt("antifurto-off");
						if(antifurtoOff != stato)
							return "off";
						int antifurtoOn = a.getInt("antifurto-on");
						if(antifurtoOn != stato)
							return "on";
					}
				}
			} catch (JSONException e) {
				if(!e.getMessage().contains("stato-attuale"))
					System.out.println(e.getMessage());
			}
//			if(riga.getInt("stato")==statoAttuale) {
//				this.statoAttuale = riga.getInt("cmd"+newStatoInterruttore);
//				aggiornaInterruttoreESuono();
//			}
		}
		return null;
	}
	
	private synchronized void setCollaterals(int stato) {
		setCollaterals(stato,false);
	}

	private synchronized void setCollaterals(int stato,boolean write) {
		switch (stato) {
			case 0: {
				this.stato = 0;
				this.learn = false;
				this.antifurto = false;
				break;
			}
			case 1: {
				this.stato = 1;
				this.learn = true;
				this.antifurto = false;
				break;
			}
			case 2: {
				this.stato = 2;
				this.learn = false;
				this.antifurto = true;
				break;
			}
		}
		unreadStatus = true;
//		notifyAll();
		if(write)
			writeStatoOnDatabase();
	}

	private synchronized void writeStatoOnDatabase() {
		try {
			this.jsonObject.put("stato-attuale", this.stato);
			Helper.scriviFile(jsonObject,DATABASE_PATH);
		} catch (JSONException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public synchronized int getStato() {
		unreadStatus = false;
		return this.stato;
	}
	
	public synchronized boolean getLearn() {
		unreadStatus = false;
		return this.learn;
	}
	
	public synchronized boolean getAntifurto() {
		unreadStatus = false;
		return this.antifurto;
	}
	
//	public synchronized boolean waitForAntifurto() {
//		while(!this.antifurto) {
//			try {
//				wait();
//			} catch(InterruptedException ex) {
//				System.out.println("Interrupted exception");
//			}
//		}
//		return this.antifurto;
//	}

}