package no.valg.valgnatt.backend.rapport;

import java.net.HttpURLConnection;

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

/**
 * Klassen representerer en mottaker av rapporter og holder tilstanden som denne mottakeren har (hvor mange rapporter er mottatt,
 * hvorvidt mottakeren er tilgjengelig på denne URL'en, etc)
 */
public class RapportMottaker {

	private static final int TJUEFIRE = 24;
	private static final Logger LOG = LogManager.getLogger(RapportMottaker.class);
	private long serverInstans;
	private String url;
	private String[] urlTabell;
	private int urlIndeks;
	private boolean tilgjengelig;
	private String feilmelding;
	private int valgår;
	private int nyesteRapportIdHosMottaker;
	private int antallGangerVentetPåRapportProduksjon;


	RapportMottaker(long serverInstans, String urlListe, int valgår) {
		this.serverInstans = serverInstans;
		this.urlTabell = urlListe.split("\\+");
		this.url = urlTabell[urlIndeks];
		this.valgår = valgår;

	}

	int getNyesteRapportIdHosMottaker() {
		return nyesteRapportIdHosMottaker;
	}

	boolean måBliOppdatert(boolean rapportOppdateringPågår, int nyesteRapportIdProdusert) {

		if (!tilgjengelig) {
			// Hoppe til neste i failover-lista, eller tilbake til den første igjen hvis vi har wrappet rundt
			if (++urlIndeks >= urlTabell.length) {
				urlIndeks = 0;
			}
			url = urlTabell[urlIndeks];
			LOG.warn(toString() + "Responderte med en feilmelding: " + feilmelding);
			return false;
		}
		if (nyesteRapportIdHosMottaker == nyesteRapportIdProdusert) {
			return false;
		}
		LOG.info(toString() + "Siste rapport-id (server/mottaker): " + nyesteRapportIdProdusert + "/" + nyesteRapportIdHosMottaker + " - krever oppdatering");
		if (rapportOppdateringPågår) {
			if (antallGangerVentetPåRapportProduksjon < TJUEFIRE) {
				antallGangerVentetPåRapportProduksjon++;
				LOG.warn(toString() + "Rapportproduksjon pågår - vi venter litt med synkroniseringen for å unngå inkonsistens mellom rapportene som skal oppdateres.");
				return false; // Rapportoppdatering pågår, vi venter til det er ferdig ELLER etter vi har ventet 24 runder (=2 minutter)
			} else {
				LOG.warn(toString() + "Rapportproduksjon har pågått mye lenger enn forventet, derfor oppdateres rapportene ut til klientene selv om det kan være " +
						"inkonsistens mellom rapportene");
			}
		}
		antallGangerVentetPåRapportProduksjon = 0; // kommer bare hit om man skal gjøre en oppdatering
		return true;
	}

	public String toString() {
		return "RapportMottaker (" + url + ") : ";
	}

	void sjekkStatus(boolean sperrefrist, boolean stemmetallMottatt) {
		try {
			String tilstand = sperrefrist ? (stemmetallMottatt ? "sperrefrist" : "sperrefrist-nullrapporter") : "publiser";
			PostToURL postToURL = new PostToURL(url, "status:" + serverInstans + ":" + valgår + ":" + tilstand).utfør();
			if (postToURL.getException() == null && postToURL.getResult() == HttpURLConnection.HTTP_OK) {
				tilgjengelig = true;
				nyesteRapportIdHosMottaker = Integer.valueOf(postToURL.getData().trim());
			} else {
				if (postToURL.getException() != null) {
					feilmelding = "" + postToURL.getException();
				} else {
					feilmelding = "Feil HTTP-kode:" + postToURL.getResult();
				}
				tilgjengelig = false;
				nyesteRapportIdHosMottaker = -1;
			}
		} catch (Exception e) {
			feilmelding = e.getMessage();
			tilgjengelig = false;
			nyesteRapportIdHosMottaker = -1;
		}
	}

	boolean oppdaterMedNyesteRapporter(String json) {
		PostToURL postToURL = new PostToURL(url, json).utfør();
		int result = postToURL.getResult();
		Exception exc = postToURL.getException();
		if (result == 0) {
			LOG.warn(toString() + "Forsøkte å oppdatere nyeste rapporter, men det feilet: " + feilmelding, exc);
		} else {
			if (result == HttpURLConnection.HTTP_OK) {
				LOG.info(toString() + "Har oppdatert rapporter, mottakers siste rapport-id er nå " + postToURL.getData());
				return true;
			} else {
				LOG.warn(toString() + "Forsøkte å oppdatere nyeste rapporter, men det feilet: " + feilmelding, exc);
			}
		}
		return false;
	}

}
