package no.valg.valgnatt.backend.mandatberegning.beregning;

import no.valg.valgnatt.database.domene.ValgType;
import no.valg.valgnatt.database.geografi.Kommune;
import no.valg.valgnatt.database.geografi.Mandater;
import no.valg.valgnatt.database.geografi.PartiMandater;
import no.valg.valgnatt.database.hibernate.Valgdistrikt;
import no.valg.valgnatt.database.hibernate.ValgdistriktId;
import org.junit.Assert;
import org.junit.Test;

import java.math.BigDecimal;

public class DistriktsmandatTest {
	@Test
	public void beregn_Enkel_A() {
		Kommune kommune = opprettKommune("A", "H", "FRP", "KRF");

		kommune.getValgdistrikt().getPartiMandater("A").getResultatData().setStemmer(300);
		kommune.getValgdistrikt().getPartiMandater("H").getResultatData().setStemmer(200);
		kommune.getValgdistrikt().getPartiMandater("FRP").getResultatData().setStemmer(150);
		kommune.getValgdistrikt().getPartiMandater("KRF").getResultatData().setStemmer(50);

		DistriktsmandatResultat resultat = Distriktsmandat.beregnOgOppdater(kommune, 2, false, false);

		Assert.assertEquals(1, (int) resultat.getAntallPrParti().get("A"));
		Assert.assertEquals(new BigDecimal("214.28571"), resultat.getSisteKvotientPrParti().get("A"));
		Assert.assertEquals(1, resultat.getLavesteMandatrangPrParti().get("A").intValue());
		Assert.assertEquals(new BigDecimal("100.00000"), resultat.getNesteKvotientPrParti().get("A"));
		Assert.assertEquals(4, resultat.getHøyesteMandatrangPrParti().get("A").intValue());
	}

	private Kommune opprettKommune(String... partikoder) {
		Kommune kommune = new Kommune("0229", "Enebakk", true, true);
		Valgdistrikt vd = new Valgdistrikt();
		ValgdistriktId valgdistriktId = new ValgdistriktId();
		valgdistriktId.setNr("0229");
		valgdistriktId.setValgType(ValgType.KO);
		vd.setId(valgdistriktId);
		kommune.setValgdistrikt(vd);
		int i = 1;
		for (String partikode : partikoder) {
			vd.addPartiMandater(new PartiMandater(partikode, partikode, "1", "" + i++, true));
		}
		return kommune;
	}

	@Test
	public void ikke_enhetstest_brukes_til_å_sjekke_en_mandatfordeling() {
		String[] partikoder = new String[]{"A", "FRP", "H", "KRF", "MDG", "SP", "SV", "ANDRE"};
		Kommune kommune = opprettKommune(partikoder);

		kommune.getValgdistrikt().getPartiMandater("A").getResultatData().setStemmer(32054);
		kommune.getValgdistrikt().getPartiMandater("FRP").getResultatData().setStemmer(9869);
		kommune.getValgdistrikt().getPartiMandater("H").getResultatData().setStemmer(11128);
		kommune.getValgdistrikt().getPartiMandater("KRF").getResultatData().setStemmer(2707);
		kommune.getValgdistrikt().getPartiMandater("MDG").getResultatData().setStemmer(1051);
		kommune.getValgdistrikt().getPartiMandater("SP").getResultatData().setStemmer(12796);
		kommune.getValgdistrikt().getPartiMandater("SV").getResultatData().setStemmer(2596);
		kommune.getValgdistrikt().getPartiMandater("ANDRE").getResultatData().setStemmer(1484);


		DistriktsmandatResultat resultat = Distriktsmandat.beregnOgOppdater(kommune, 4, false, false);
		StringBuilder sb = new StringBuilder();

		for (String partikode : partikoder) {
			PartiMandater pm = kommune.getValgdistrikt().getPartiMandater(partikode);
			Mandater mandater = pm.getResultatData().getDistriktsmandater();
			sb.append("\t")
                    .append(partikode)
                    .append(" : ")
                    .append(pm.getResultatData().getStemmer())
                    .append(" -> ")
                    .append(resultat.getAntallPrParti().get(partikode))
                    .append(" - ")
                    .append(mandatInformasjon(mandater))
                    .append("\n");
		}
		System.out.println("Distriktmandatberegning: \n" + sb.toString());
	}

	private String mandatInformasjon(Mandater mandater) {
        return "Siste mandat: " +
                mandater.getLavesteKvotientMedMandat() +
                " (rang " +
                mandater.getLavesteMandatrangMedMandat() +
                "), neste mandat: " +
                mandater.getHøyesteKvotientUtenMandat() +
                "(rang " +
                mandater.getHøyesteMandatrangUtenMandat() +
                ")";
	}

	@Test
	public void beregn_Grensetilfelle_A() {
		Kommune kommune = opprettKommune("A", "H", "FRP", "KRF");

		kommune.getValgdistrikt().getPartiMandater("A").getResultatData().setStemmer(200);
		kommune.getValgdistrikt().getPartiMandater("H").getResultatData().setStemmer(200);
		kommune.getValgdistrikt().getPartiMandater("FRP").getResultatData().setStemmer(200);
		kommune.getValgdistrikt().getPartiMandater("KRF").getResultatData().setStemmer(200);

		DistriktsmandatResultat resultat = Distriktsmandat.beregnOgOppdater(kommune, 2, false, false);

		// Mandater fordeles etter alfabetisk rekkefølge! Dette er *ikke*
		// korrekt etter valgloven - den krever loddtrekning. Det kan
		// ikke dette systemet gjøre *på samme måte* som Admin-systemet - og
		// dermed er det ingen vits i å prøve å gjøre noe slikt heller.
		Assert.assertEquals(1, (int) resultat.getAntallPrParti().get("A"));
        Assert.assertNull(resultat.getAntallPrParti().get("H"));
		Assert.assertEquals(1, (int) resultat.getAntallPrParti().get("FRP"));
        Assert.assertNull(resultat.getAntallPrParti().get("KRF"));
	}

}
