package no.valg.valgnatt.mottak;

import no.valg.valgnatt.database.EvaAdminSkjema;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;

/**
 * MottakServlet har 2 hovedmetoder
 * <p/>
 * 1. doPost() tar i mot data fra EVA Admin og/eller Simulator/StemmeInnsender (se valg_utils-pakken). Data kan være på forskjellige former:
 * a) Stemmeskjema : Et stemmeskjema som gir opplysninger om stemmer for en gitt stemmekrets. Dette er selvsagt det helt sentrale bruksområdet
 * for denne klassen, og det eneste som MÅ fungere under en valggjennomføring.
 * b) Grunnlagsdata: Her finnes det flere former for skjema:
 * - Stemmekrets: Inneholder info stemmekretser (m/stemmeberettigede), bydeler, kommuner og fylker. I sum: en full geografisk struktur
 * - Kandidater: Inneholder informasjon om alle kandidater som stiller i ST-valg
 * - Etc...
 * <p/>
 * 2. doGet() finner fram et stemmeskjema fra stemmeskjema-tabellen og returnerer dette til klienten. Dette er en funksjon som har blitt
 * lagt til senere, og som ikke har noe med selve kjøringen av Valgnatt å gjøre. Formålet er å kunne (se Configuration.mottakFromURL)
 * levere data til en annen Valgnatt-instans som kjører som en skygge-instans. Typisk brukstilfellet er at man har en Valgnatt-instans som
 * kjører lokalt med fullt utviklingsmiljø, og som henter sine stemmeskjema fra en produksjon/stage-instans av Valgnatt.
 */
public class MottakServlet extends HttpServlet {

	private static final Logger LOG = LogManager.getLogger(MottakServlet.class);
	private static final int FØRSTE_TOHUNDRE_TEGN = 200;

	private MainMottak mainMottak;

	@Override
	public void init() throws ServletException {
		mainMottak = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()).getBean(MainMottak.class);
	}

	@Override
	public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		int refId = -1;
		String id = req.getParameter("id");
		if (id != null) {
			try {
				refId = Integer.parseInt(id);
			} catch (NumberFormatException e) {
				// Nothing
			}
		}
		if (refId < 1) {
			res.sendError(HttpServletResponse.SC_BAD_REQUEST, "id parameter missing or non-numeric");
		} else {
			String data = mainMottak.getData(refId);
			if (data == null) {
				res.sendError(HttpServletResponse.SC_NOT_FOUND, "no data found with this id");
			} else {
				res.setContentType("application/json");
				res.setCharacterEncoding("utf-8");
				PrintWriter out = res.getWriter();
				out.print(data);
				out.close();
			}
		}
	}

	@Override
	public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException {
		try {
			håndterSkjemaFraAdmin(req, res);
		} catch (Exception e) {
			LOG.error("Feil oppstod: " + e, e);
			throw new ServletException("Feil oppstod i MottakServlet.doPost()", e);
		}
	}

	private void håndterSkjemaFraAdmin(HttpServletRequest req, HttpServletResponse res) throws IOException {
		try {
			StringBuilder sb = new StringBuilder();
			req.setCharacterEncoding("utf-8");
			BufferedReader br = req.getReader();
			String line;
			while ((line = br.readLine()) != null) {
				sb.append(line).append('\n');
			}
			br.close();
			String data = sb.toString();
			if (data.startsWith("stemmeskjemafradiversesiden=")) {
				data = URLDecoder.decode(data, "UTF-8");
				data = data.substring("stemmeskjemafradiversesiden=".length(),data.indexOf("&button=Send"));
				LOG.info("Mottok manuelt innsendt stemmeskjema via valg_overvaking fra adresse " + req.getRemoteAddr() + ":\n" + data);
			}
			EvaAdminSkjema evaAdminSkjema = new EvaAdminSkjema(data);
			if (evaAdminSkjema.erStemmeskjema()) {
				mainMottak.lagreStemmeskjema(data, req.getRemoteAddr());
			} else if (evaAdminSkjema.erGrunnlagsskjema()) {
				evaAdminSkjema.skrivTilFil();
				LOG.info("Lagret skjema til " + System.getProperty("jboss.server.data.dir") + File.separator + evaAdminSkjema.getFilnavn());
				if (evaAdminSkjema.erStemmekretsSkjema() && mainMottak.finnesGrunnlag(evaAdminSkjema)) {
					LOG.info("Skal oppdatere stemmeberettigede i alle stemmekretser");
					mainMottak.oppdaterStemmeberettigede(evaAdminSkjema);
					LOG.info("Har oppdatert stemmeberettigede i alle stemmekretser");
				}
			} else {
				throw new MottakException("Mottok data fra " + req.getRemoteAddr() + " med ugyldig innhold som starter med " +
						(data.length() > FØRSTE_TOHUNDRE_TEGN ? data.substring(0, FØRSTE_TOHUNDRE_TEGN) : data));
			}
			res.setContentType("text/plain");
			res.getWriter().println("OK");
		} catch (MottakException me) {
			res.sendError(HttpServletResponse.SC_BAD_REQUEST, me.getMessage());
			LOG.warn(me.getMessage());
		}
	}

}
