package no.valg.valgnatt.backend.rapport;

import no.valg.valgnatt.backend.MainBackend;
import no.valg.valgnatt.common.ValgnattException;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Sender implements Runnable {

	private static final int TITUSEN = 10000;
	private static final Logger LOG = LogManager.getLogger(Sender.class);

	private static final int LØKKE_INTERVALL = 5000; // 5 sek
	private String urlListe;
	private MainRapport mainRapport;
	private boolean offentlig;

	// Disse vil bli endret/lest av forskjellige tråder (Sender, Hovedloop, Servlet)
	private volatile boolean stopp;
	private volatile boolean rapportProduksjonPågår;
	private volatile boolean rapportMottakerOppdatert;

	Sender(String urlListe, MainRapport mainRapport, boolean offentlig) {
		// urlListe representerer én enkelt mottaker av rapporter (med mulighet for failover (skilt med +))
		this.urlListe = urlListe;
		this.mainRapport = mainRapport;
		this.offentlig = offentlig;
	}

	void start() {
		(new Thread(this)).start();
	}

	@Override
	public void run() {
		Thread.currentThread().setName("Sender til " + urlListe);
		long serverInstansNr = MainBackend.getInstance() % TITUSEN;
		LOG.info("Starter Sender-tråd (serverinstans " + serverInstansNr + ") med urListe: " + urlListe + ", offentlig: " + offentlig);
		RapportMottaker rapportMottaker = new RapportMottaker(serverInstansNr, urlListe, mainRapport.getValgAar());
		while (!stopp) {
			try {
				vent(LØKKE_INTERVALL);
				boolean sperrefrist = mainRapport.sperrefrist(offentlig);
				boolean stemmetallMottatt = mainRapport.stemmetallMottatt();
				rapportMottaker.sjekkStatus(sperrefrist, stemmetallMottatt);
				if (sperrefrist && stemmetallMottatt) {
					LOG.info("Sperrefrist gjelder for " + urlListe + " og stemmetall er mottatt - vi sender ingenting til Frontend");
					rapportMottakerOppdatert = true;
				} else {
					sjekkOgOppdaterKlient(rapportMottaker);
				}
			} catch (Exception e) {
				LOG.error("Alvorlig feil oppstod i Sender.run() med URL-spesifikasjon: " + urlListe + ". Vi forsøker igjen. Feilen var: " + e.getMessage(), e);
			}
		}
	}

	private void sjekkOgOppdaterKlient(RapportMottaker rapportMottaker) {
		int nyesteRapportIdProdusert = mainRapport.getRapporterIdMap().size() == 0 ? 0 : mainRapport.getRapporterIdMap().lastKey();
		if (rapportMottaker.måBliOppdatert(rapportProduksjonPågår, nyesteRapportIdProdusert)) {
			String rapporterJson = mainRapport.rapporter2JsonSamlerapport(rapportMottaker.getNyesteRapportIdHosMottaker());
			rapportMottakerOppdatert = rapportMottaker.oppdaterMedNyesteRapporter(rapporterJson);
		} else if (rapportMottaker.getNyesteRapportIdHosMottaker() == nyesteRapportIdProdusert) {
			rapportMottakerOppdatert = true; // sikrer oss at dette flagget alltid vil bli satt til syvende og sist
		}
	}

	private void vent(long intervall) {
		try {
			Thread.sleep(intervall);
		} catch (InterruptedException e) {
			throw new ValgnattException(e);
		}
	}

	void starterRapportProduksjon() {
		rapportProduksjonPågår = true;
		rapportMottakerOppdatert = false;
	}

	void avslutterRapportProduksjon() {
		rapportMottakerOppdatert = false;
		rapportProduksjonPågår = false;
	}

	boolean rapportProduksjonPågår() {
		return rapportProduksjonPågår;
	}

	void stopp() {
		stopp = true;
	}

	boolean erRapportMottakerOppdatert() {
		return rapportMottakerOppdatert;
	}
}
